Verification Object: Design Specification and Code for Synchronous FIFO
Verification object for beginner tasks
Design Specification
Module Name
SyncFIFO
Description
This module implements a 32-bit wide synchronous FIFO (First-In-First-Out) buffer with a capacity of 16 elements. The FIFO is used to temporarily store data, providing write and read operations, and supports full/empty status indication. It features clock-synchronized behavior, suitable for data stream processing, interface buffering, and other scenarios. This design follows synchronous operation using a single clock signal for both read and write.
Port Description
| Port Name | Direction | Width (bit) | Description |
|---|---|---|---|
| clk | input | 1 | Clock signal |
| rst_n | input | 1 | Active-low reset signal; initializes the FIFO when low |
| we_i | input | 1 | Write enable signal, active-high; when 1, allows data to be written to the FIFO |
| re_i | input | 1 | Read enable signal, active-high; when 1, allows data to be read from the FIFO |
| data_i | input | 32 | Data to be written to the FIFO |
| data_o | output | 32 | Data read from the FIFO |
| full_o | output | 1 | Indicates whether the FIFO is full |
| empty_o | output | 1 | Indicates whether the FIFO is empty |
Functional Description
Write Operation:
When
we_iis 1, the FIFO can receive data and store it into the internal bufferram.The write pointer
wptrindicates the next write position and increments with each write operation.When the FIFO is full,
full_ois 1 and the write operation is invalid.
Read Operation:
When
re_iis 1, the FIFO outputs data fromrambased on the read pointerrptr.The read pointer
rptrindicates the next read position and increments with each read operation.When the FIFO is empty,
empty_ois 1 and the read operation is invalid.
Pointer Update:
wptr(write pointer) andrptr(read pointer) are updated on the rising edge of the clock.rptris updated only whenre_iis valid and the FIFO is not empty;wptris updated only whenwe_iis valid and the FIFO is not full.During FIFO operation, by comparing the positions of
wptrandrptr, the FIFO automatically adjusts the read and write positions of data.
Counter:
counteris used to track the amount of data in the FIFO (from 0 to 16). Each time data is written,counteris incremented by 1; each time data is read,counteris decremented by 1.When
counteris 0, theempty_osignal is 1, indicating the FIFO is empty; whencounteris 16, thefull_osignal is 1, indicating the FIFO is full.
Timing and Reset
Synchronous Timing: All operations (write, read, pointer update, counter update) are synchronized to the rising edge of the clock signal.
Reset: When
rst_nis low, all internal pointers (wptr,rptr) and data output (data_o) of the FIFO are cleared, and the countercounteris reset to 0.
Functional Block Description
Pointer Update:
Responsible for synchronously updating write and read pointers.
Within each clock cycle, if
we_iis 1 and the FIFO is not full, data is written to the FIFO andwptrincrements.If
re_iis 1 and the FIFO is not empty, data is read and output, andrptrincrements.
Counter Update:
The counter
counteris used to track the current amount of data in the FIFO.Each write operation increments
counter; each read operation decrementscounter.When the FIFO is full,
counterreaches 16 andfull_ois 1; when the FIFO is empty,counteris 0 andempty_ois 1.
Design Constraints and Assumptions
Data Width and Depth: This design uses a 32-bit width and 16-depth FIFO, suitable for small-scale data caching requirements.
Clock Domain: The FIFO module is designed to operate in a single clock domain, and the clock and reset signals are synchronous.
Data Storage: The FIFO data is stored in a 16-element RAM array, with each element being 32 bits.
Simultaneous Read/Write: When the FIFO is neither full nor empty, simultaneous read and write operations are allowed.
Boundary Conditions
When the FIFO is full and the
we_isignal is high, the write operation is blocked.When the FIFO is empty and the
re_isignal is high, the read operation is blocked.
Design Code
module SyncFIFO (
input wire clk,
input wire rst_n,
input wire we_i,
input wire re_i,
input wire [31:0] data_i,
output reg [31:0] data_o,
output wire full_o,
output wire empty_o
);
reg [31:0] ram[16];
reg [3:0] wptr;
reg [3:0] rptr;
reg [4:0] counter;
wire rvalid, wvalid;
assign rvalid = re_i && !empty_o;
assign wvalid = we_i && !full_o;
always @(posedge clk) begin : PTR_UPDATE
if (!rst_n) begin
wptr <= 0;
rptr <= 0;
data_o <= 0;
end else begin
if (rvalid) begin
rptr <= rptr + 1;
data_o <= ram[rptr];
end
if (wvalid) begin
wptr <= wptr + 1;
ram[wptr] <= data_i;
end
end
end
always @(posedge clk) begin : COUNTER_UPDATE
if (!rst_n) counter <= 0;
else if (rvalid ^ wvalid) begin
if (rvalid) counter <= counter - 1;
if (wvalid) counter <= counter + 1;
end
end
assign full_o = counter == 5'd16;
assign empty_o = counter == 0;
endmodule