OpenCores
URL https://opencores.org/ocsvn/open_free_list/open_free_list/trunk

Subversion Repositories open_free_list

[/] [open_free_list/] [trunk/] [hdl/] [open_free_list.v] - Blame information for rev 3

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 amif2000
module open_free_list #(parameter RAM_W = 128, RAM_E = 0, RAM_S = 64, CNK_S = 128, RAM_TYPE = "MRAM", FL_AEMPTY_LVL=2) (
2
  input  wire                                 reset_n,
3
  input  wire                                 clk,
4
  // Write side
5
  output wire [clog2((RAM_S*1024)/CNK_S)-1:0] fl_q,
6
  output wire                                 fl_aempty,
7
  output wire                                 fl_empty,
8
  input  wire                                 wren,
9
  input  wire [RAM_W+RAM_E-1:0]               din,
10
  input  wire                                 eop,
11
  // Read side
12
  input  wire [clog2((RAM_S*1024)/CNK_S)-1:0] chunk_num,
13
  input  wire                                 load_req,
14
  input  wire                                 rel_req,
15
  output reg                                  load_rel_ack,
16
  input  wire                                 rden,
17
  output wire [RAM_W+RAM_E-1:0]               dout
18
);
19
 
20
localparam FL_S = (RAM_S*1024)/CNK_S;
21
localparam FL_W = clog2(FL_S);
22
localparam FL_ADDR_W = FL_W;
23
localparam LL_W = FL_W+1;
24
localparam RAM_ADDR_W = clog2((RAM_S*1024)/(RAM_W/8));
25
localparam LINES_IN_CNK = CNK_S/(RAM_W/8);
26
localparam IN_CNK_ADDR_W = clog2(LINES_IN_CNK);
27
 
28
 
29
wire [RAM_W+RAM_E-1:0]  ram_q;
30
reg  [RAM_ADDR_W-1:0]   ram_rd_addr;
31
wire [RAM_ADDR_W-1:0]   ram_wr_addr;
32
reg  [RAM_ADDR_W-1:0]   ram_wr_addr_lat;
33
reg                     wr_eop_while_ll;
34
reg  [FL_W-1:0]         fl_data;
35
wire [FL_ADDR_W-1:0]    fl_lvl;
36
reg                     fl_rden;
37
reg                     fl_wren;
38
wire [FL_W:0]           ll_data;
39
wire [FL_W:0]           ll_q;
40
reg  [FL_ADDR_W-1:0]    ll_rd_addr;
41
wire [FL_ADDR_W-1:0]    ll_wr_addr;
42
wire                    ll_wren;
43
wire                    ll_eop;
44
 
45
reg  [FL_ADDR_W-1:0]    fl_init_cnt;
46
reg                     fl_init;
47
reg                     fl_init_r1;
48
reg                     fl_init_r2;
49
reg                     fl_init_r3;
50
reg                     fl_init_wr;
51
 
52
reg                     int_sop;
53
reg                     rel_req_from_idle;
54
 
55
wire                    load_req_p;
56
wire [FL_ADDR_W-1:0]    nxt_chunk_ptr;
57
 
58
reg  [2:0]              ns_rd_sm;
59
reg  [2:0]              cs_rd_sm;
60
parameter               IDLE           = 3'd0,
61
                        PREFETCH       = 3'd1,
62
                        RD             = 3'd2,
63
                        WAIT_REL       = 3'd3,
64
                        REL_DELAY1     = 3'd4,
65
                        REL_DELAY2     = 3'd5,
66
                        REL_WR2FL      = 3'd6;
67
 
68
reg                     sm_rel_ctrl;
69
reg                     sm_rel_wren;
70 3 amif2000
reg                                             sm_rel_ctrl_mask;
71
reg                                             sm_rel_ctrl_mask_clr;
72
reg                                             sm_rel_ctrl_mask_set;
73 2 amif2000
 
74
reg                     int_rden;
75
reg                     load_req_r1;
76
reg  [RAM_ADDR_W-1:0]   usr_ram_rd_addr_r1;
77
 
78
altsyncram3 ram (
79
  .data       (din),
80
  .rd_aclr    (~reset_n),
81
  .rdaddress  (ram_rd_addr),
82
  .rdclock    (clk),
83
  .rdclocken  (int_rden | rden),
84
  .wraddress  (ram_wr_addr),
85
  .wrclock    (clk),
86
  .wrclocken  (1'b1),
87
  .wren       (wren),
88
  .q          (dout)
89
);
90
defparam
91
  ram.A_WIDTH   = RAM_W+RAM_E,
92
  ram.A_WIDTHAD = RAM_ADDR_W,
93
  ram.RAM_TYPE  = RAM_TYPE,
94
  ram.USE_RDEN  = 0;
95
 
96
alt_scfifo free_list(
97
  .aclr          (~reset_n),
98
  .clock         (clk),
99
  .data          (fl_init_wr ? fl_init_cnt : fl_data),
100
  .rdreq         (fl_rden),
101
  .sclr          (1'b0),
102
  .wrreq         (fl_init_wr | fl_wren),
103
  .almost_empty  (fl_aempty),
104
  .almost_full   (),
105
  .empty         (fl_empty),
106
  .full          (),
107
  .q             (fl_q),
108
  .usedw         (fl_lvl)
109
);
110
defparam
111
   free_list.FIFO_WIDTH    = FL_W,
112
   free_list.FIFO_DEPTH    = FL_ADDR_W,
113
   free_list.FIFO_TYPE     = "M4K",
114
   free_list.FIFO_SHOW     = "ON",
115
   free_list.FIFO_AEMPTY   = FL_AEMPTY_LVL;
116
 
117
 
118
altsyncram3 link_list(
119
  .data       (ll_data),
120
  .rd_aclr    (~reset_n),
121
  .rdaddress  (sm_rel_ctrl ? nxt_chunk_ptr : ll_rd_addr),
122
  .rdclock    (clk),
123
  .rdclocken  (1'b1),
124
  .wraddress  (ll_wr_addr),
125
  .wrclock    (clk),
126
  .wrclocken  (1'b1),
127
  .wren       (ll_wren),
128
  .q          (ll_q)
129
);
130
defparam
131
  link_list.A_WIDTH   = LL_W,
132
  link_list.A_WIDTHAD = FL_ADDR_W,
133
  link_list.RAM_TYPE  = "M4K",
134
  link_list.USE_RDEN  = 0;
135
 
136
 
137
// Free list init
138
 
139
always @ (posedge clk, negedge reset_n)
140
begin
141
  if (reset_n==1'b0)
142
  begin
143
    fl_init_cnt <= {FL_ADDR_W{1'b0}};
144
    fl_init     <= 1'b0;
145
    fl_init_r1  <= 1'b0;
146
    fl_init_r2  <= 1'b0;
147
    fl_init_r3  <= 1'b0;
148
    fl_init_wr  <= 1'b0;
149
  end
150
  else
151
  begin
152
    fl_init_cnt <= fl_init_wr ? fl_init_cnt + 1'b1 : {FL_ADDR_W{1'b0}};
153
    fl_init     <= 1'b1;
154
    fl_init_r1  <= fl_init;
155
    fl_init_r2  <= fl_init_r1;
156
    fl_init_r3  <= fl_init_r2;
157
    fl_init_wr  <= !fl_init_r3 && fl_init_r2 ? 1'b1 : fl_init_cnt=={FL_ADDR_W{1'b1}} ?  1'b0 : fl_init_wr;
158
  end
159
end
160
 
161
 
162
// Write side
163
 
164
assign ram_wr_addr = int_sop || (wren && ram_wr_addr_lat[IN_CNK_ADDR_W-1:0]==(LINES_IN_CNK-1)) ? {fl_q, {IN_CNK_ADDR_W{1'b0}}}
165
                                                                                               : wren ? ram_wr_addr_lat + 1'b1
166
                                                                                                      : ram_wr_addr_lat;
167
assign ll_eop      = wren && ram_wr_addr[IN_CNK_ADDR_W-1:0]==0 && eop ? 1'b0 : eop | wr_eop_while_ll;
168
assign ll_wr_addr  = ram_wr_addr_lat[RAM_ADDR_W-1:IN_CNK_ADDR_W];
169
assign ll_data     = {fl_q, ll_eop};
170
assign ll_wren     = (wren && ((ram_wr_addr[IN_CNK_ADDR_W-1:0]==0) || eop)) || wr_eop_while_ll ? 1'b1 : 1'b0;
171
 
172
 
173
always @ (posedge clk, negedge reset_n)
174
begin
175
  if (reset_n==1'b0)
176
  begin
177
    fl_rden         <= 1'b0;
178
    int_sop         <= 1'b1;
179
    ram_wr_addr_lat <= {RAM_ADDR_W{1'b0}};
180
    wr_eop_while_ll <= 1'b0;
181
  end
182
  else
183
  begin
184
    fl_rden         <= wren && (ram_wr_addr[IN_CNK_ADDR_W-1:0]==0) ? 1'b1 : 1'b0;
185
    int_sop         <= wren && eop ? 1'b1 :
186
                       wren        ? 1'b0 :
187
                                     int_sop;
188
    ram_wr_addr_lat <= ram_wr_addr;
189
    wr_eop_while_ll <= wren && ram_wr_addr[IN_CNK_ADDR_W-1:0]==0 && eop ? 1'b1 : 1'b0;
190
  end
191
end
192
 
193
// Read side
194
assign load_req_p    = ~load_req_r1 & load_req;
195
assign nxt_chunk_ptr = ll_q[FL_W:1]; //can be sampled
196
 
197
always @*
198
begin
199
  case(cs_rd_sm)
200
    IDLE:
201
      ns_rd_sm = fl_init_wr ? IDLE       :
202
                 rel_req    ? REL_DELAY1 :
203
                 load_req   ? PREFETCH   :
204
                              IDLE;
205
    PREFETCH:
206
      ns_rd_sm = RD;
207
    RD:
208
      ns_rd_sm = load_req                                                                     ? PREFETCH  :
209
                 rden && (usr_ram_rd_addr_r1[IN_CNK_ADDR_W-1:0]==(LINES_IN_CNK-1)) && ll_q[0] ? WAIT_REL  : // true if the current chunk is the last chunk and was reached to its end and is released now                                                                                           : REL_WR2FL // true if the current chunk was reached to its end and is released now and is the last one
210
                 rel_req                                                                      ? REL_WR2FL :
211
                                                                                                                                                                                RD;
212
    WAIT_REL:
213
      ns_rd_sm = rel_req ? IDLE : WAIT_REL;
214
    REL_DELAY1:
215
      ns_rd_sm = REL_DELAY2;
216
    REL_DELAY2:
217
      ns_rd_sm = REL_WR2FL;
218
    REL_WR2FL:
219
      ns_rd_sm = ll_q[0] ? IDLE : REL_DELAY2;
220
  endcase
221
end
222
 
223
always @*
224
begin
225 3 amif2000
  rel_req_from_idle    = 1'b0;
226
  int_rden             = 1'b0;
227
  load_rel_ack         = 1'b0;
228
  sm_rel_ctrl_mask_set = 1'b0;
229
  sm_rel_ctrl_mask_clr = 1'b0;
230
  sm_rel_ctrl          = 1'b1;
231
  sm_rel_wren          = 1'b0;
232 2 amif2000
  case(cs_rd_sm)
233
    IDLE:
234
    begin
235 3 amif2000
      rel_req_from_idle    = rel_req;
236
      sm_rel_ctrl_mask_set = rel_req;
237
      sm_rel_ctrl          = 1'b0;
238 2 amif2000
    end
239
    PREFETCH:
240
    begin
241
      int_rden      = 1'b1;
242
      load_rel_ack  = 1'b1;
243
      sm_rel_ctrl   = 1'b0;
244
    end
245
    RD:
246
    begin
247
      sm_rel_ctrl   = 1'b0;
248
    end
249
    WAIT_REL:
250
    begin
251
      load_rel_ack = rel_req;
252
    end
253
    REL_DELAY1:
254
    begin
255 3 amif2000
      sm_rel_ctrl = ~sm_rel_ctrl_mask;
256 2 amif2000
    end
257
    REL_DELAY2:
258
    begin
259 3 amif2000
      sm_rel_ctrl = ~sm_rel_ctrl_mask;
260 2 amif2000
    end
261
    REL_WR2FL:
262
    begin
263
      sm_rel_wren  = 1'b1;
264
      load_rel_ack = ll_q[0];
265 3 amif2000
      sm_rel_ctrl_mask_clr = 1'b1;
266 2 amif2000
    end
267
  endcase
268
end
269
 
270
always @ (posedge clk, negedge reset_n)
271
begin
272
  if (reset_n==1'b0)
273
  begin
274
    cs_rd_sm           <= 3'd0;
275
    load_req_r1        <= 1'b0;
276 3 amif2000
    sm_rel_ctrl_mask   <= 1'b0;
277 2 amif2000
    ll_rd_addr         <= {FL_ADDR_W{1'b0}};
278
    ram_rd_addr        <= {RAM_ADDR_W{1'b0}};
279
    usr_ram_rd_addr_r1 <= {RAM_ADDR_W{1'b0}};
280
    fl_wren            <= 1'b0;
281
    fl_data            <= {FL_W{1'b0}};
282
  end
283
  else
284
  begin
285
    cs_rd_sm           <= ns_rd_sm;
286
    load_req_r1        <= load_req;
287 3 amif2000
    sm_rel_ctrl_mask   <= sm_rel_ctrl_mask_set ? 1'b1 :
288
                          sm_rel_ctrl_mask_clr ? 1'b0 :
289
                                                 sm_rel_ctrl_mask;
290 2 amif2000
 
291
    ll_rd_addr         <= load_req_p  || rel_req_from_idle                                                                     ? chunk_num     :
292
                          sm_rel_wren || ((!sm_rel_ctrl && rden && (usr_ram_rd_addr_r1[IN_CNK_ADDR_W-1:0]==(LINES_IN_CNK-1)))) ? nxt_chunk_ptr :
293
                                                                                                                                 ll_rd_addr;
294
    ram_rd_addr        <= load_req_p                                                 ? {chunk_num,  {IN_CNK_ADDR_W{1'b0}}}     :
295
                          rden && (ram_rd_addr[IN_CNK_ADDR_W-1:0]==(LINES_IN_CNK-1)) ? {nxt_chunk_ptr,  {IN_CNK_ADDR_W{1'b0}}} :
296
                          rden || int_rden                                           ? ram_rd_addr + 1'b1                      :
297
                                                                                       ram_rd_addr;
298
    usr_ram_rd_addr_r1 <= !sm_rel_ctrl && (rden || int_rden) ? ram_rd_addr : usr_ram_rd_addr_r1;
299
    fl_wren            <= (!sm_rel_ctrl && rden && (usr_ram_rd_addr_r1[IN_CNK_ADDR_W-1:0]==(LINES_IN_CNK-1))) || sm_rel_wren ? 1'b1 : 1'b0;
300
    fl_data            <= rel_req_from_idle ? chunk_num  :
301
                          sm_rel_wren       ? ll_rd_addr :
302
                                              usr_ram_rd_addr_r1[RAM_ADDR_W-1:IN_CNK_ADDR_W];
303
 
304
  end
305
end
306
 
307
/********************************************************
308
  clog2 - function that returns log2 of a value rounded up
309
        - min return value is 1 (in case of clog2(1)=1)
310
 ********************************************************/
311
function integer clog2(input integer value);
312
begin
313
  value = value-1;
314
  for (clog2=0; value>0; clog2=clog2+1)
315
    value = value>>1;
316
  if (clog2 == 0)
317
    clog2 = 1;
318
end
319
endfunction
320
 
321
endmodule

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.