// 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