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 2

Go to most recent revision | 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
 
71
reg                     rden_r1;
72
reg                     int_rden;
73
reg                     int_rden_r1;
74
reg                     load_req_r1;
75
reg  [RAM_ADDR_W-1:0]   usr_ram_rd_addr_r1;
76
 
77
altsyncram3 ram (
78
  .data       (din),
79
  .rd_aclr    (~reset_n),
80
  .rdaddress  (ram_rd_addr),
81
  .rdclock    (clk),
82
  .rdclocken  (int_rden | rden),
83
  .wraddress  (ram_wr_addr),
84
  .wrclock    (clk),
85
  .wrclocken  (1'b1),
86
  .wren       (wren),
87
  .q          (dout)
88
);
89
defparam
90
  ram.A_WIDTH   = RAM_W+RAM_E,
91
  ram.A_WIDTHAD = RAM_ADDR_W,
92
  ram.RAM_TYPE  = RAM_TYPE,
93
  ram.USE_RDEN  = 0;
94
 
95
alt_scfifo free_list(
96
  .aclr          (~reset_n),
97
  .clock         (clk),
98
  .data          (fl_init_wr ? fl_init_cnt : fl_data),
99
  .rdreq         (fl_rden),
100
  .sclr          (1'b0),
101
  .wrreq         (fl_init_wr | fl_wren),
102
  .almost_empty  (fl_aempty),
103
  .almost_full   (),
104
  .empty         (fl_empty),
105
  .full          (),
106
  .q             (fl_q),
107
  .usedw         (fl_lvl)
108
);
109
defparam
110
   free_list.FIFO_WIDTH    = FL_W,
111
   free_list.FIFO_DEPTH    = FL_ADDR_W,
112
   free_list.FIFO_TYPE     = "M4K",
113
   free_list.FIFO_SHOW     = "ON",
114
   free_list.FIFO_AEMPTY   = FL_AEMPTY_LVL;
115
 
116
 
117
altsyncram3 link_list(
118
  .data       (ll_data),
119
  .rd_aclr    (~reset_n),
120
  .rdaddress  (sm_rel_ctrl ? nxt_chunk_ptr : ll_rd_addr),
121
  .rdclock    (clk),
122
  .rdclocken  (1'b1),
123
  .wraddress  (ll_wr_addr),
124
  .wrclock    (clk),
125
  .wrclocken  (1'b1),
126
  .wren       (ll_wren),
127
  .q          (ll_q)
128
);
129
defparam
130
  link_list.A_WIDTH   = LL_W,
131
  link_list.A_WIDTHAD = FL_ADDR_W,
132
  link_list.RAM_TYPE  = "M4K",
133
  link_list.USE_RDEN  = 0;
134
 
135
 
136
// Free list init
137
 
138
always @ (posedge clk, negedge reset_n)
139
begin
140
  if (reset_n==1'b0)
141
  begin
142
    fl_init_cnt <= {FL_ADDR_W{1'b0}};
143
    fl_init     <= 1'b0;
144
    fl_init_r1  <= 1'b0;
145
    fl_init_r2  <= 1'b0;
146
    fl_init_r3  <= 1'b0;
147
    fl_init_wr  <= 1'b0;
148
  end
149
  else
150
  begin
151
    fl_init_cnt <= fl_init_wr ? fl_init_cnt + 1'b1 : {FL_ADDR_W{1'b0}};
152
    fl_init     <= 1'b1;
153
    fl_init_r1  <= fl_init;
154
    fl_init_r2  <= fl_init_r1;
155
    fl_init_r3  <= fl_init_r2;
156
    fl_init_wr  <= !fl_init_r3 && fl_init_r2 ? 1'b1 : fl_init_cnt=={FL_ADDR_W{1'b1}} ?  1'b0 : fl_init_wr;
157
  end
158
end
159
 
160
 
161
// Write side
162
 
163
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}}}
164
                                                                                               : wren ? ram_wr_addr_lat + 1'b1
165
                                                                                                      : ram_wr_addr_lat;
166
assign ll_eop      = wren && ram_wr_addr[IN_CNK_ADDR_W-1:0]==0 && eop ? 1'b0 : eop | wr_eop_while_ll;
167
assign ll_wr_addr  = ram_wr_addr_lat[RAM_ADDR_W-1:IN_CNK_ADDR_W];
168
assign ll_data     = {fl_q, ll_eop};
169
assign ll_wren     = (wren && ((ram_wr_addr[IN_CNK_ADDR_W-1:0]==0) || eop)) || wr_eop_while_ll ? 1'b1 : 1'b0;
170
 
171
 
172
always @ (posedge clk, negedge reset_n)
173
begin
174
  if (reset_n==1'b0)
175
  begin
176
    fl_rden         <= 1'b0;
177
    int_sop         <= 1'b1;
178
    ram_wr_addr_lat <= {RAM_ADDR_W{1'b0}};
179
    wr_eop_while_ll <= 1'b0;
180
  end
181
  else
182
  begin
183
    fl_rden         <= wren && (ram_wr_addr[IN_CNK_ADDR_W-1:0]==0) ? 1'b1 : 1'b0;
184
    int_sop         <= wren && eop ? 1'b1 :
185
                       wren        ? 1'b0 :
186
                                     int_sop;
187
    ram_wr_addr_lat <= ram_wr_addr;
188
    wr_eop_while_ll <= wren && ram_wr_addr[IN_CNK_ADDR_W-1:0]==0 && eop ? 1'b1 : 1'b0;
189
  end
190
end
191
 
192
// Read side
193
assign load_req_p    = ~load_req_r1 & load_req;
194
assign nxt_chunk_ptr = ll_q[FL_W:1]; //can be sampled
195
 
196
always @*
197
begin
198
  case(cs_rd_sm)
199
    IDLE:
200
      ns_rd_sm = fl_init_wr ? IDLE       :
201
                 rel_req    ? REL_DELAY1 :
202
                 load_req   ? PREFETCH   :
203
                              IDLE;
204
    PREFETCH:
205
      ns_rd_sm = RD;
206
    RD:
207
      ns_rd_sm = load_req                                                                     ? PREFETCH  :
208
                 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
209
                 rel_req                                                                      ? REL_WR2FL :
210
                                                                                                                                                                                RD;
211
    WAIT_REL:
212
      ns_rd_sm = rel_req ? IDLE : WAIT_REL;
213
    REL_DELAY1:
214
      ns_rd_sm = REL_DELAY2;
215
    REL_DELAY2:
216
      ns_rd_sm = REL_WR2FL;
217
    REL_WR2FL:
218
      ns_rd_sm = ll_q[0] ? IDLE : REL_DELAY2;
219
  endcase
220
end
221
 
222
always @*
223
begin
224
  rel_req_from_idle = 1'b0;
225
  int_rden          = 1'b0;
226
  load_rel_ack      = 1'b0;
227
  sm_rel_ctrl       = 1'b1;
228
  sm_rel_wren       = 1'b0;
229
  case(cs_rd_sm)
230
    IDLE:
231
    begin
232
      rel_req_from_idle = rel_req;
233
      sm_rel_ctrl       = rel_req;
234
    end
235
    PREFETCH:
236
    begin
237
      int_rden      = 1'b1;
238
      load_rel_ack  = 1'b1;
239
      sm_rel_ctrl   = 1'b0;
240
    end
241
    RD:
242
    begin
243
      sm_rel_ctrl   = 1'b0;
244
    end
245
    WAIT_REL:
246
    begin
247
      load_rel_ack = rel_req;
248
    end
249
    REL_DELAY1:
250
    begin
251
    end
252
    REL_DELAY2:
253
    begin
254
    end
255
    REL_WR2FL:
256
    begin
257
      sm_rel_wren  = 1'b1;
258
      load_rel_ack = ll_q[0];
259
    end
260
  endcase
261
end
262
 
263
always @ (posedge clk, negedge reset_n)
264
begin
265
  if (reset_n==1'b0)
266
  begin
267
    cs_rd_sm           <= 3'd0;
268
    rden_r1            <= 1'b0;
269
    int_rden_r1        <= 1'b0;
270
    load_req_r1        <= 1'b0;
271
    ll_rd_addr         <= {FL_ADDR_W{1'b0}};
272
    ram_rd_addr        <= {RAM_ADDR_W{1'b0}};
273
    usr_ram_rd_addr_r1 <= {RAM_ADDR_W{1'b0}};
274
    fl_wren            <= 1'b0;
275
    fl_data            <= {FL_W{1'b0}};
276
  end
277
  else
278
  begin
279
    cs_rd_sm           <= ns_rd_sm;
280
    rden_r1            <= rden;
281
    int_rden_r1        <= int_rden;
282
    load_req_r1        <= load_req;
283
 
284
    ll_rd_addr         <= load_req_p  || rel_req_from_idle                                                                     ? chunk_num     :
285
                          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 :
286
                                                                                                                                 ll_rd_addr;
287
    ram_rd_addr        <= load_req_p                                                 ? {chunk_num,  {IN_CNK_ADDR_W{1'b0}}}     :
288
                          rden && (ram_rd_addr[IN_CNK_ADDR_W-1:0]==(LINES_IN_CNK-1)) ? {nxt_chunk_ptr,  {IN_CNK_ADDR_W{1'b0}}} :
289
                          rden || int_rden                                           ? ram_rd_addr + 1'b1                      :
290
                                                                                       ram_rd_addr;
291
    usr_ram_rd_addr_r1 <= !sm_rel_ctrl && (rden || int_rden) ? ram_rd_addr : usr_ram_rd_addr_r1;
292
    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;
293
    fl_data            <= rel_req_from_idle ? chunk_num  :
294
                          sm_rel_wren       ? ll_rd_addr :
295
                                              usr_ram_rd_addr_r1[RAM_ADDR_W-1:IN_CNK_ADDR_W];
296
 
297
  end
298
end
299
 
300
/********************************************************
301
  clog2 - function that returns log2 of a value rounded up
302
        - min return value is 1 (in case of clog2(1)=1)
303
 ********************************************************/
304
function integer clog2(input integer value);
305
begin
306
  value = value-1;
307
  for (clog2=0; value>0; clog2=clog2+1)
308
    value = value>>1;
309
  if (clog2 == 0)
310
    clog2 = 1;
311
end
312
endfunction
313
 
314
endmodule

powered by: WebSVN 2.1.0

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