Create list_ch04_20_fifo.v
diff --git a/verilog/rtl/list_ch04_20_fifo.v b/verilog/rtl/list_ch04_20_fifo.v new file mode 100644 index 0000000..a75ff51 --- /dev/null +++ b/verilog/rtl/list_ch04_20_fifo.v
@@ -0,0 +1,92 @@ +// 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 +