Table of contents of FIFO series articles:
Verilog function module – asynchronous FIFO-CSDN blog
Verilog function module – synchronous FIFO-CSDN blog
Verilog function module – asynchronous FIFO with different read and write bit widths-CSDN Blog
Verilog function module – synchronous FIFO with different read and write bit widths-CSDN Blog
Verilog function module – standard FIFO to FWFT FIFO-CSDN blog
Preface
Preface
The previous blog post has talked about asynchronous FIFO, asynchronous FIFO with different read and write bit widths, and synchronous FIFO. This article uses pure Verilog to implement a synchronous FIFO with different read and write bit widths, and simulates to verify the correctness of the design.
1. Implementation ideas
1. Implementation ideas
The idea is exactly the same as the asynchronous FIFO with different read and write bit widths, except that the asynchronous FIFO submodule is replaced by the synchronous FIFO submodule.
Notice:
- Synchronous FIFO does not have “false full” or “false empty” problems
- The actual capacity of the FIFO is larger than the set capacity, and the difference is 2 small bits wide (read/write) data
2. Module functional block diagram and signal description
2. Module functional block diagram and signal description
Signal description:
Classification | Signal name | Input/output | Description |
---|---|---|---|
Parameters | DIN_WIDTH | – | Input data bit width |
DOUT_WIDTH | – | Output data bit width | |
WADDR_WIDTH | – | Write address bit width, FIFO depth=2**WADDR_WIDTH | |
FWFT_EN | – | First word fall-through output mode is enabled, high level is active | |
MSB_FIFO | – | 1 (default value) means high-order first-in-first-out, 0 means low-order first-in First-out For example, if 4 bits are input and 8 bits are output, the first input is considered to be the high 4 bits of 8 bits. The next input is considered to be the lower 4 bits of 8bit. In the same way, if you input 8 bits and output 4 bits, the high 4 bits of the 8 bits will be output first. What is output next is the lower 4 bits of 8bit. Vivado FIFO only has high-order first-in-first-out |
|
FIFO write port | din | input | FIFO data input |
full | output | FIFO full signal | |
wr_en | input | FIFO write enable | |
almost_full | output | FIFO almost full signal, set high when FIFO remaining capacity <=1 | |
FIFO read port | dout | output | FIFO data output |
empty | output | FIFO empty signal | |
rd_en | input | FIFO read enable | |
almost_empty | output | FIFO fast empty signal, set high when the amount of data in FIFO <=1 | |
Clock domain reset | clk | input | FIFO clock |
rst | input | FIFO reset | |
Notice:
-
The naming of the signals is exactly the same as the FIFO IP core in Vivado
-
All resets are high-level resets, consistent with the FIFO IP core in Vivado
-
Reset is an asynchronous reset. Write reset and read reset can share the same signal or can be separated.
-
The FIFO depth is set by WADDR_WIDTH, so the FIFO depth must be an index of 2, such as 4, 8, 16, 32, etc.
-
The multiple relationship between DIN_WIDTH and DOUT_WIDTH must be 2 to the nth power, such as 2 times, 4 times, 8 times, and cannot be 3 times or 6 times.
-
WADDR_WIDTH must be ≥ 2, and RADDR_WIDTH = WADDR_WIDTH + log2(DIN_WIDTH / DOUT_WIDTH) must also be ≥ 2
A limit case, DIN_WIDTH = 4, DOUT_WIDTH=16, WADDR_WIDTH=4, RADDR_WIDTH =4 + log2(4/16)=2
-
MSB_FIFO is used to set the high-bit/low-bit first-in-first-out. It is not the same concept as the generally talked about FIFO big-endian and little-endian modes.
3. Partial code display
3. Partial code display
//~ If the read bit width is greater than the write bit width, the data needs to be combined, and the combined data into one data is written to the read side FIFO. if (DOUT_WIDTH >= DIN_WIDTH) begin wire wdata_almost_full; syncFIFO # ( .DATA_WIDTH (DIN_WIDTH), .ADDR_WIDTH (1 ), .FWFT_EN (1) ) syncFIFO_u0 ( .din (din ), .wr_en (wr_en ), .full (full), .almost_full (wdata_almost_full), .dout(wdata), .rd_en (wdata_rd_en), .empty (wdata_empty), .almost_empty ( ), .clk (clk), .rst (rst) ); assign almost_full = (wdata_almost_full & amp; & amp; rdata_full) || full; localparam RADDR_WIDTH = $clog2(2**WADDR_WIDTH * DIN_WIDTH / DOUT_WIDTH); syncFIFO # ( .DATA_WIDTH (DOUT_WIDTH ), .ADDR_WIDTH (RADDR_WIDTH), .FWFT_EN (FWFT_EN ) ) syncFIFO_u1 ( .din(rdata), .wr_en (rdata_wr_en ), .full (rdata_full ), .almost_full ( ), .dout (dout), .rd_en (rd_en ), .empty (empty), .almost_empty (almost_empty), .clk (clk), .rst (rst) ); // Read the write-side FIFO when the read-side FIFO is not full and the write-side FIFO is not empty. assign wdata_rd_en = ~rdata_full & amp; & amp; ~wdata_empty; reg [DOUT_WIDTH-1:0] rdata_r; if (MSB_FIFO == 1) begin always @(posedge clk or posedge rst) begin if(rst) rdata_r <= 'd0; else if (wdata_rd_en) rdata_r <= {rdata_r[DOUT_WIDTH-DIN_WIDTH-1:0], wdata}; // The advanced bit is the high bit else rdata_r <= rdata_r; end assign rdata = {rdata_r[DOUT_WIDTH-DIN_WIDTH-1:0], wdata}; // The advanced bit is the high bit end else begin always @(posedge clk or posedge rst) begin if(rst) rdata_r <= 'd0; else if (wdata_rd_en) rdata_r <= {wdata, rdata_r[DOUT_WIDTH-1 : DIN_WIDTH]}; // The advanced one is the low bit else rdata_r <= rdata_r; end assign rdata = {wdata, rdata_r[DOUT_WIDTH-1 : DIN_WIDTH]}; // The advanced one is the low bit end localparam WDATA_RD_EN_CNT_MAX = DOUT_WIDTH / DIN_WIDTH - 1; reg [$clog2(WDATA_RD_EN_CNT_MAX + 1)-1 : 0] wdata_rd_en_cnt; always @(posedge clk or posedge rst) begin if(rst) wdata_rd_en_cnt <= 'd0; else if (wdata_rd_en) wdata_rd_en_cnt <= wdata_rd_en_cnt + 1'b1; else wdata_rd_en_cnt <= wdata_rd_en_cnt; end assign rdata_wr_en = wdata_rd_en & amp; & amp; wdata_rd_en_cnt == WDATA_RD_EN_CNT_MAX; end
4. Functional simulation
4. Functional simulation
The simulation is basically the same as the previous situation of asynchronous FIFO with different read and write bit widths, except that the read and write clocks are the same.
testbench, there are also project sharing at the end of the article, students can check it out by themselves.
Write 4bit, write depth 32, read 8bit, FWFT FIFO simulation, the waveform is as follows:
It can be seen that after writing two 4-bit data, empty is pulled low after delaying two rising edges of the read clock, and the data becomes 8’h01. After reading, empty is set high again, and the read port logic is normal. The Vivado FIFO IP’s empty signal has a large delay in pulling low, but it also ensures that the data is valid when empty is pulled low.
As can be seen from the above figure, the full signal and almost_full signal can be set high normally, and then read one data and delay the rising edges of two write clocks to pull them low together. Because reading data once is equivalent to 2 write data, almost_full It is pulled down together with full, which is also correct. The actual depth of the Vivado FIFO IP is larger than the set 32, which is why the full value of this IP is set later than the full value of the module.
It can be seen that the read data of the module is the same as the read data of Vivado FIFO IP. At the end, after the module FIFO reads 8’h23, empty is set high. Because of the greater depth of Vivado IP, empty is set high later. It can be seen that the read port behavior is correct.
Due to space constraints, simulations under other conditions are no longer shown. Interested students can verify it themselves by changing the testbench.
- Change FWFT_EN to 0, and be careful to modify the configuration of Vivado FIFO simultaneously.
- Verify that the write data bit width > the read data bit width
5. Project sharing
5. Project sharing
Verilog functional module – synchronous FIFO with different read and write bit widths, Vivado 2021.2 project.
Welcome everyone to follow my public account: Xu Xiaokang’s blog, and reply to the following four-digit number to get it.
8304
It is recommended to copy it to avoid typos!
Or get it from my code cloud warehouse, portal:
Xu Xiaokang/Verilog Function Module – Code Cloud – Open Source China (gitee.com)
Xu Xiaokang’s blog continues to share high-quality hardware, FPGA and embedded knowledge, software, tools and other content. Everyone is welcome to pay attention.