aboutsummaryrefslogtreecommitdiffstats
path: root/fpga/usrp2/extramfifo/fifo_extram.v
blob: 4e1f40371ba6d253df65a5ed498889cc5a5ae97a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
// Everything on sram_clk

module fifo_extram
  (input reset, input clear,
   input [17:0] datain, input src_rdy_i, output dst_rdy_o, output [15:0] space, input [15:0] occ_in,
   output [17:0] dataout, output src_rdy_o, input dst_rdy_i, output [15:0] occupied, input [15:0] space_in,
   input sram_clk, output [18:0] sram_a, inout [17:0] sram_d, output sram_we,
   output [1:0] sram_bw, output sram_adv, output sram_ce, output sram_oe, 
   output sram_mode, output sram_zz);

   localparam AWIDTH   = 19; // 1 MB in x18
   localparam RAMSIZE  = ((1<<AWIDTH) - 1);

   wire   do_store, do_retrieve;
   reg [1:0]  do_store_del, do_retr_del;
   
   reg [AWIDTH-1:0] addr_retrieve, addr_store;
   always @(posedge sram_clk)
     if(reset | clear)
       addr_retrieve <= 0;
     else if (do_retrieve)
       addr_retrieve <= addr_retrieve + 1;
   
   always @(posedge sram_clk)
     if(reset | clear)
       addr_store    <= 0;
     else if(do_store)
       addr_store    <= addr_store + 1;

   //wire [AWIDTH-1:0] fullness = (addr_store - addr_retrieve);
   reg [AWIDTH-1:0] fullness;
   always @(posedge sram_clk)
     if(reset | clear)
       fullness      <= 0;
     else if(do_store)
       fullness      <= fullness + 1;
     else if(do_retrieve)
       fullness      <= fullness - 1;
   
   //   wire        empty  = (fullness == 0);
   //wire        full   = (fullness == RAMSIZE); // 19'h7FF);
   reg 		    empty, full;
   
   //  The math in the following functions is 'AWIDTH wide.  Use
   //  continuous assignments to prevent the numbers from being
   //  promoted to 32-bit (which would make it wrap wrong).
   //
   wire [AWIDTH-1:0] addr_retrieve_p1, addr_store_p2;
   assign addr_retrieve_p1 = addr_retrieve + 1;
   assign addr_store_p2 = addr_store + 2;

   always @(posedge sram_clk)
     if(reset | clear)
       empty 	     <= 1;
     else if(do_store)
       empty 	     <= 0;
     else if(do_retrieve & (/*(addr_retrieve + 1)*/ addr_retrieve_p1 == addr_store))
       empty 	     <= 1;
   
   always @(posedge sram_clk)
     if(reset | clear)
       full 	     <= 0;
     else if(do_retrieve)
       full 	     <= 0;
     else if(do_store & (/*(addr_store+2)*/ addr_store_p2 == addr_retrieve))
       full <= 1;

   reg 	       can_store;
   always @*
     if(full | ~src_rdy_i)
       can_store 	  <= 0;
     else if(do_store_del == 0)
       can_store 	  <= 1;
     else if((do_store_del == 1) || (do_store_del == 2))
       can_store 	  <= (occ_in > 1);
     else
       can_store 	  <= (occ_in > 2);
     
   reg 	       can_retrieve;
   always @*
     if(empty | ~dst_rdy_i)
       can_retrieve 	     <= 0;
     else if(do_retr_del == 0)
       can_retrieve 	     <= 1;
     else if((do_retr_del == 1) || (do_retr_del == 2))
       can_retrieve 	     <= (space_in > 1);
     else
       can_retrieve 	     <= (space_in > 2);
   
   reg [1:0]  state;
   localparam IDLE_STORE_NEXT  = 0;
   localparam STORE 	       = 1;
   localparam IDLE_RETR_NEXT   = 2;
   localparam RETRIEVE 	       = 3;
   
   reg [7:0]  countdown;
   wire       countdown_done 		   = (countdown == 0);

   localparam CYCLE_SIZE 		   = 6;
   
   assign        do_store 		   = can_store & (state == STORE);
   assign        do_retrieve 		   = can_retrieve & (state == RETRIEVE);
   always @(posedge sram_clk)
     if(reset)
       do_store_del 			  <= 0;
     else
       do_store_del 			  <= {do_store_del[0],do_store};
   
   always @(posedge sram_clk) 
     if(reset)
       do_retr_del <= 0;
     else
       do_retr_del <= {do_retr_del[0],do_retrieve};

   always @(posedge sram_clk)
     if(reset | clear)
       begin
	  state 			  <= IDLE_STORE_NEXT;
	  countdown 			  <= 0;
       end
     else
       case(state)
	 IDLE_STORE_NEXT :
	   if(can_store)
	     begin
		state 	  <= STORE;
		countdown <= CYCLE_SIZE;
	     end
	   else if(can_retrieve)
	     begin
		state 	  <= RETRIEVE;
		countdown <= CYCLE_SIZE;
	     end
	 STORE :
	   if(~can_store | (can_retrieve & countdown_done))
	     state <= IDLE_RETR_NEXT;
	   else if(~countdown_done)
	     countdown <= countdown - 1;
	 IDLE_RETR_NEXT :
	   if(can_retrieve)
	     begin
		state 	  <= RETRIEVE;
		countdown <= CYCLE_SIZE;
	     end
	   else if(can_store)
	     begin
		state 	  <= STORE;
		countdown <= CYCLE_SIZE;
	     end
	 RETRIEVE :
	   if(~can_retrieve | (can_store & countdown_done))
	     state <= IDLE_STORE_NEXT;
	   else if(~countdown_done)
	     countdown <= countdown - 1;
       endcase // case (state)

   // RAM wires
   assign sram_bw      = 0;
   assign sram_adv     = 0;
   assign sram_mode    = 0;
   assign sram_zz      = 0;
   assign sram_ce      = 0;

   assign sram_a       = (state==STORE) ? addr_store : addr_retrieve;
   assign sram_we      = ~do_store;
   assign sram_oe      = ~do_retr_del[1];
   assign my_oe        = do_store_del[1] & sram_oe;
   assign sram_d       = my_oe ? datain : 18'bz;
   
   // FIFO wires
   assign dataout      = sram_d;
   assign src_rdy_o    = do_retr_del[1];
   assign dst_rdy_o    = do_store_del[1];
   
endmodule // fifo_extram


   //wire        have_1 		   = (fullness == 1);
   //wire        have_2 		   = (fullness == 2);
   //wire        have_atleast_1 	   = ~empty;
   //wire        have_atleast_2 	   = ~(empty | have_1);
   //wire        have_atleast_3 	   = ~(empty | have_1 | have_2);   
   //wire        full_minus_1 	   = (fullness == (RAMSIZE-1)); // 19'h7FE);
   //wire        full_minus_2 	   = (fullness == (RAMSIZE-2)); // 19'h7FD);
   //wire        spacefor_atleast_1  = ~full;
   //wire        spacefor_atleast_2  = ~(full | full_minus_1);
   //wire        spacefor_atleast_3  = ~(full | full_minus_1 | full_minus_2);