Visible to Intel only — GUID: mes1526933103280
Ixiasoft
Answers to Top FAQs
1. Hyperflex® FPGA Architecture Introduction
2. Hyperflex® Architecture RTL Design Guidelines
3. Compiling Hyperflex® Architecture Designs
4. Design Example Walk-Through
5. Retiming Restrictions and Workarounds
6. Optimization Example
7. Hyperflex® Architecture Porting Guidelines
8. Appendices
9. Hyperflex® Architecture High-Performance Design Handbook Archive
10. Hyperflex® Architecture High-Performance Design Handbook Revision History
2.4.2.1. High-Speed Clock Domains
2.4.2.2. Restructuring Loops
2.4.2.3. Control Signal Backpressure
2.4.2.4. Flow Control with FIFO Status Signals
2.4.2.5. Flow Control with Skid Buffers
Skid Buffer Example (Single Clock)
Skid Buffer Example (Dual Clock)
2.4.2.6. Read-Modify-Write Memory
2.4.2.7. Counters and Accumulators
2.4.2.8. State Machines
2.4.2.9. Memory
2.4.2.10. DSP Blocks
2.4.2.11. General Logic
2.4.2.12. Modulus and Division
2.4.2.13. Resets
2.4.2.14. Hardware Re-use
2.4.2.15. Algorithmic Requirements
2.4.2.16. FIFOs
2.4.2.17. Ternary Adders
5.2.1. Insufficient Registers
5.2.2. Short Path/Long Path
5.2.3. Fast Forward Limit
5.2.4. Loops
5.2.5. One Critical Chain per Clock Domain
5.2.6. Critical Chains in Related Clock Groups
5.2.7. Complex Critical Chains
5.2.8. Extend to locatable node
5.2.9. Domain Boundary Entry and Domain Boundary Exit
5.2.10. Critical Chains with Dual Clock Memories
5.2.11. Critical Chain Bits and Buses
5.2.12. Delay Lines
Visible to Intel only — GUID: mes1526933103280
Ixiasoft
2.4.2.5. Flow Control with Skid Buffers
You can use skid buffers to pipeline a FIFO. If necessary, you can cascade skid buffers. When you insert skid buffers, they unroll the loop that includes the FIFO control signals. The skid buffers do not eliminate the loop in the flow control logic, but the loop transforms into a series of shorter loops. In general, switch to almost empty and almost full signals instead of using skid buffers when possible.
Figure 71. FIFO Flow Control Loop with Two Skid Buffers in a Read Control Loop
If you have loops involving FIFO control signals, and they are broadcast to many destinations for flow control, consider whether you can eliminate the broadcast signals. Pipeline broadcast control signals, and use almost full and almost empty status bits from FIFOs.
Skid Buffer Example (Single Clock)
/ synopsys translate_off //`timescale 1 ps / 1 ps // synopsys translate_on module singleclock_fifo_lowell #( parameter DATA_WIDTH = 8, parameter FIFO_DEPTH = 16, parameter SHOWAHEAD = "ON", // "ON" = showahead mode ('pop' is an acknowledgement); / "OFF" = normal mode ('pop' is a request). parameter RAM_TYPE = "AUTO", // "AUTO" or "MLAB" or "M20K". // Derived parameter ADDR_WIDTH = $clog2(FIFO_DEPTH) + 1 // e.g. clog2(64) = 6, but 7 bits / needed to store 64 value ) ( input wire clk, input wire rst, input wire [DATA_WIDTH-1:0] in_data, // write data input wire pop, // rd request input wire push, // wr request output wire out_valid, // not empty output wire in_ready, // not full output wire [DATA_WIDTH-1:0] out_data, // rd data output wire [ADDR_WIDTH-1:0] fill_level ); wire scfifo_empty; wire scfifo_full; wire [DATA_WIDTH-1:0] scfifo_data_out; wire [ADDR_WIDTH-1:0] scfifo_usedw; logic [DATA_WIDTH-1:0] out_data_1q; logic [DATA_WIDTH-1:0] out_data_2q; logic out_empty_1q; logic out_empty_2q; logic e_pop_1; logic e_pop_2; logic e_pop_qual; assign out_valid = ~out_empty_2q; assign in_ready = ~scfifo_full; assign out_data = out_data_2q; assign fill_level = scfifo_usedw + !out_empty_1q + !out_empty_2q; // add output pipe assign e_pop_1 = out_empty_1q || e_pop_2; assign e_pop_2 = out_empty_2q || pop; assign e_pop_qual = !scfifo_empty && e_pop_1; always_ff@(posedge clk) begin if(rst == 1'b1) begin out_empty_1q <= 1'b1; // empty is 1 by default out_empty_2q <= 1'b1; // empty is 1 by default end else begin if(e_pop_1) begin out_empty_1q <= scfifo_empty; end if(e_pop_2) begin out_empty_2q <= out_empty_1q; end end end always_ff@(posedge clk) begin if(e_pop_1) out_data_1q <= scfifo_data_out; if(e_pop_2) out_data_2q <= out_data_1q; end scfifo scfifo_component ( .clock (clk), .data (in_data), .rdreq (e_pop_qual), .wrreq (push), .empty (scfifo_empty), .full (scfifo_full), .q (scfifo_data_out), .usedw (scfifo_usedw), // .aclr (rst), .aclr (1'b0), .almost_empty (), .almost_full (), .eccstatus (), //.sclr (1'b0) .sclr (rst) // switch to sync reset ); defparam scfifo_component.add_ram_output_register = "ON", scfifo_component.enable_ecc = "FALSE", scfifo_component.intended_device_family = "Stratix", scfifo_component.lpm_hint = (RAM_TYPE == "MLAB") ? "RAM_BLOCK_TYPE=MLAB" : / ((RAM_TYPE == "M20K") ? "RAM_BLOCK_TYPE=M20K" : ""), scfifo_component.lpm_numwords = FIFO_DEPTH, scfifo_component.lpm_showahead = SHOWAHEAD, scfifo_component.lpm_type = "scfifo", scfifo_component.lpm_width = DATA_WIDTH, scfifo_component.lpm_widthu = ADDR_WIDTH, scfifo_component.overflow_checking = "ON", scfifo_component.underflow_checking = "ON", scfifo_component.use_eab = "ON"; endmodule
Skid Buffer Example (Dual Clock)
// synopsys translate_off //`timescale 1 ps / 1 ps // synopsys translate_on module skid_dualclock_fifo #( parameter DATA_WIDTH = 8, parameter FIFO_DEPTH = 16, parameter SHOWAHEAD = "ON", parameter RAM_TYPE = "AUTO", // "AUTO" or "MLAB" or "M20K". // Derived parameter ADDR_WIDTH = $clog2(FIFO_DEPTH) + 1 ) ( input wire rd_clk, input wire wr_clk, input wire rst, input wire [DATA_WIDTH-1:0] in_data, // write data input wire pop, // rd request input wire push, // wr request output wire out_valid, // not empty output wire in_ready, // not full output wire [DATA_WIDTH-1:0] out_data, // rd data output wire [ADDR_WIDTH-1:0] fill_level ); wire scfifo_empty; wire scfifo_full; wire [DATA_WIDTH-1:0] scfifo_data_out; wire [ADDR_WIDTH-1:0] scfifo_usedw; logic [DATA_WIDTH-1:0] out_data_1q; logic [DATA_WIDTH-1:0] out_data_2q; logic out_empty_1q; logic out_empty_2q; logic e_pop_1; logic e_pop_2; logic e_pop_qual; assign out_valid = ~out_empty_2q; assign in_ready = ~scfifo_full; assign out_data = out_data_2q; assign fill_level = scfifo_usedw + !out_empty_1q + !out_empty_2q; // add output pipe assign e_pop_1 = out_empty_1q || e_pop_2; assign e_pop_2 = out_empty_2q || pop; assign e_pop_qual = !scfifo_empty && e_pop_1; always_ff@(posedge rd_clk) begin if(rst == 1'b1) begin out_empty_1q <= 1'b1; // empty is 1 by default out_empty_2q <= 1'b1; // empty is 1 by default end else begin if(e_pop_1) begin out_empty_1q <= scfifo_empty; end if(e_pop_2) begin out_empty_2q <= out_empty_1q; end end end always_ff@(posedge rd_clk) begin if(e_pop_1) out_data_1q <= scfifo_data_out; if(e_pop_2) out_data_2q <= out_data_1q; end dcfifo dcfifo_component ( .data (in_data), .rdclk (rd_clk), .rdreq (e_pop_qual), .wrclk (wr_clk), .wrreq (push), .q (scfifo_data_out), .rdempty (scfifo_empty), .rdusedw (scfifo_usedw), .wrfull (scfifo_full), .wrusedw (), .aclr (1'b0), .eccstatus (), .rdfull (), .wrempty () ); defparam dcfifo_component.add_usedw_msb_bit = "ON", dcfifo_component.enable_ecc = "FALSE", dcfifo_component.intended_device_family = "Stratix 10", dcfifo_component.lpm_hint = (RAM_TYPE == "MLAB") \ ? "RAM_BLOCK_TYPE=MLAB" : ((RAM_TYPE == "M20K") \ ? "RAM_BLOCK_TYPE=M20K" : ""), dcfifo_component.lpm_numwords = FIFO_DEPTH, dcfifo_component.lpm_showahead = SHOWAHEAD, dcfifo_component.lpm_type = "dcfifo", dcfifo_component.lpm_width = DATA_WIDTH, dcfifo_component.lpm_widthu = ADDR_WIDTH+1, dcfifo_component.overflow_checking = "ON", dcfifo_component.read_aclr_synch = "ON", dcfifo_component.rdsync_delaypipe = 5, dcfifo_component.underflow_checking = "ON", dcfifo_component.write_aclr_synch = "ON", dcfifo_component.use_eab = "ON", dcfifo_component.wrsync_delaypipe = 5; endmodule