blob: a6931226f39b1f9ac6010a11a206d9d251da9f1c [file] [log] [blame]
// 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