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
+