1 | // Listing 4.20
|
---|
2 | module fifo
|
---|
3 | #(
|
---|
4 | parameter B=8, // number of bits in a word
|
---|
5 | W=4 // number of address bits
|
---|
6 | )
|
---|
7 | (
|
---|
8 | input wire clk, reset,
|
---|
9 | input wire rd, wr,
|
---|
10 | input wire [B-1:0] w_data,
|
---|
11 | output wire empty, full,
|
---|
12 | output wire [B-1:0] r_data
|
---|
13 | );
|
---|
14 |
|
---|
15 | //signal declaration
|
---|
16 | reg [B-1:0] array_reg [2**W-1:0]; // register array
|
---|
17 | reg [W-1:0] w_ptr_reg, w_ptr_next, w_ptr_succ;
|
---|
18 | reg [W-1:0] r_ptr_reg, r_ptr_next, r_ptr_succ;
|
---|
19 | reg full_reg, empty_reg, full_next, empty_next;
|
---|
20 | wire wr_en;
|
---|
21 |
|
---|
22 | // body
|
---|
23 | // register file write operation
|
---|
24 | always @(posedge clk)
|
---|
25 | if (wr_en)
|
---|
26 | array_reg[w_ptr_reg] <= w_data;
|
---|
27 | // register file read operation
|
---|
28 | assign r_data = array_reg[r_ptr_reg];
|
---|
29 | // write enabled only when FIFO is not full
|
---|
30 | assign wr_en = wr & ~full_reg;
|
---|
31 |
|
---|
32 | // fifo control logic
|
---|
33 | // register for read and write pointers
|
---|
34 | always @(posedge clk, posedge reset)
|
---|
35 | if (reset)
|
---|
36 | begin
|
---|
37 | w_ptr_reg <= 0;
|
---|
38 | r_ptr_reg <= 0;
|
---|
39 | full_reg <= 1'b0;
|
---|
40 | empty_reg <= 1'b1;
|
---|
41 | end
|
---|
42 | else
|
---|
43 | begin
|
---|
44 | w_ptr_reg <= w_ptr_next;
|
---|
45 | r_ptr_reg <= r_ptr_next;
|
---|
46 | full_reg <= full_next;
|
---|
47 | empty_reg <= empty_next;
|
---|
48 | end
|
---|
49 |
|
---|
50 | // next-state logic for read and write pointers
|
---|
51 | always @*
|
---|
52 | begin
|
---|
53 | // successive pointer values
|
---|
54 | w_ptr_succ = w_ptr_reg + 1;
|
---|
55 | r_ptr_succ = r_ptr_reg + 1;
|
---|
56 | // default: keep old values
|
---|
57 | w_ptr_next = w_ptr_reg;
|
---|
58 | r_ptr_next = r_ptr_reg;
|
---|
59 | full_next = full_reg;
|
---|
60 | empty_next = empty_reg;
|
---|
61 | case ({wr, rd})
|
---|
62 | // 2'b00: no op
|
---|
63 | 2'b01: // read
|
---|
64 | if (~empty_reg) // not empty
|
---|
65 | begin
|
---|
66 | r_ptr_next = r_ptr_succ;
|
---|
67 | full_next = 1'b0;
|
---|
68 | if (r_ptr_succ==w_ptr_reg)
|
---|
69 | empty_next = 1'b1;
|
---|
70 | end
|
---|
71 | 2'b10: // write
|
---|
72 | if (~full_reg) // not full
|
---|
73 | begin
|
---|
74 | w_ptr_next = w_ptr_succ;
|
---|
75 | empty_next = 1'b0;
|
---|
76 | if (w_ptr_succ==r_ptr_reg)
|
---|
77 | full_next = 1'b1;
|
---|
78 | end
|
---|
79 | 2'b11: // write and read
|
---|
80 | begin
|
---|
81 | w_ptr_next = w_ptr_succ;
|
---|
82 | r_ptr_next = r_ptr_succ;
|
---|
83 | end
|
---|
84 | endcase
|
---|
85 | end
|
---|
86 |
|
---|
87 | // output
|
---|
88 | assign full = full_reg;
|
---|
89 | assign empty = empty_reg;
|
---|
90 |
|
---|
91 | endmodule
|
---|
92 |
|
---|