Visible to Intel only — GUID: mes1526933103280
Ixiasoft
1. Intel® Hyperflex™ FPGA Architecture Introduction
2. Intel® Hyperflex™ Architecture RTL Design Guidelines
3. Compiling Intel® Hyperflex™ Architecture Designs
4. Design Example Walk-Through
5. Retiming Restrictions and Workarounds
6. Optimization Example
7. Intel® Hyperflex™ Architecture Porting Guidelines
8. Appendices
9. Intel® Hyperflex™ Architecture High-Performance Design Handbook Archive
10. Intel® 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 67. 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