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

+