// Listing 4.20 | |
module fifo | |
#( | |
parameter B=8, // number of bits in a word | |
W=4 // number of address bits | |
) | |
( | |
input wire clk, reset, | |
input wire rd, wr, | |
input wire [B-1:0] w_data, | |
output wire empty, full, | |
output wire [B-1:0] r_data | |
); | |
//signal declaration | |
reg [B-1:0] array_reg [2**W-1:0]; // register array | |
reg [W-1:0] w_ptr_reg, w_ptr_next, w_ptr_succ; | |
reg [W-1:0] r_ptr_reg, r_ptr_next, r_ptr_succ; | |
reg full_reg, empty_reg, full_next, empty_next; | |
wire wr_en; | |
// body | |
// register file write operation | |
always @(posedge clk) | |
if (wr_en) | |
array_reg[w_ptr_reg] <= w_data; | |
// register file read operation | |
assign r_data = array_reg[r_ptr_reg]; | |
// write enabled only when FIFO is not full | |
assign wr_en = wr & ~full_reg; | |
// fifo control logic | |
// register for read and write pointers | |
always @(posedge clk, posedge reset) | |
if (reset) | |
begin | |
w_ptr_reg <= 0; | |
r_ptr_reg <= 0; | |
full_reg <= 1'b0; | |
empty_reg <= 1'b1; | |
end | |
else | |
begin | |
w_ptr_reg <= w_ptr_next; | |
r_ptr_reg <= r_ptr_next; | |
full_reg <= full_next; | |
empty_reg <= empty_next; | |
end | |
// next-state logic for read and write pointers | |
always @* | |
begin | |
// successive pointer values | |
w_ptr_succ = w_ptr_reg + 1; | |
r_ptr_succ = r_ptr_reg + 1; | |
// default: keep old values | |
w_ptr_next = w_ptr_reg; | |
r_ptr_next = r_ptr_reg; | |
full_next = full_reg; | |
empty_next = empty_reg; | |
case ({wr, rd}) | |
// 2'b00: no op | |
2'b01: // read | |
if (~empty_reg) // not empty | |
begin | |
r_ptr_next = r_ptr_succ; | |
full_next = 1'b0; | |
if (r_ptr_succ==w_ptr_reg) | |
empty_next = 1'b1; | |
end | |
2'b10: // write | |
if (~full_reg) // not full | |
begin | |
w_ptr_next = w_ptr_succ; | |
empty_next = 1'b0; | |
if (w_ptr_succ==r_ptr_reg) | |
full_next = 1'b1; | |
end | |
2'b11: // write and read | |
begin | |
w_ptr_next = w_ptr_succ; | |
r_ptr_next = r_ptr_succ; | |
end | |
endcase | |
end | |
// output | |
assign full = full_reg; | |
assign empty = empty_reg; | |
endmodule | |