仅对英特尔可见 — GUID: mes1526933103280
Ixiasoft
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. 使用FIFO状态信号的流程控制
2.4.2.5. 包含skid缓冲器的流程控制
Skid Buffer示例(单时钟)
Skid Buffer示例(双时钟)
2.4.2.6. Read-Modify-Write存储器
2.4.2.7. 计数器和累加器
2.4.2.8. 状态机
2.4.2.9. 储存器
2.4.2.10. DSP模块
2.4.2.11. 一般逻辑
2.4.2.12. 求模与除法
2.4.2.13. 复位
2.4.2.14. 硬件重用
2.4.2.15. 算法要求
2.4.2.16. FIFO
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. 回路(loop)
5.2.5. 每个时钟域一个关键链
5.2.6. 相关时钟组中的关键链
5.2.7. 复杂的关键链
5.2.8. 延伸到可定位的节点
5.2.9. 域边界入口和域边界出口(Domain Boundary Entry and Domain Boundary Exit)
5.2.10. 包括双时钟存储器的关键链
5.2.11. 关键链比特和总线
5.2.12. 延迟线
仅对英特尔可见 — GUID: mes1526933103280
Ixiasoft
2.4.2.5. 包含skid缓冲器的流程控制
您可以使用skid缓冲器来对FIFO进行流水线化。如果必要,您可以级联skid缓冲器。当插入skid缓冲器时,它们展开了包括FIFO控制信号的环路。 skid缓冲器不会消除流控逻辑中的环路,但是环路变换成一系列更短的环路。一般情况下,要尽可能地切换到almost empty和almost full信号,而不是使用skid缓冲器。
图 63. 读控制中有两个skid缓冲器的FIFO流控环路
如果环路包含FIFO控制信号,并且这些FIFO控制信号广播到很多目的地以用于流控,那么您要仔细考虑是否有消除这些广播信号的方法。对广播控制信号进行流水线化,并使用FIFO的almost full和almost empty状态比特。
Skid Buffer示例(单时钟)
/ 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示例(双时钟)
// 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