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

Subversion Repositories tv80

[/] [tv80/] [trunk/] [rtl/] [app_localcfg/] [lcfg_memctl.v] - Blame information for rev 105

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 101 ghutchis
/* Copyright (c) 2011, Guy Hutchison
2
   All rights reserved.
3
 
4
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
5
 
6
    * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
7
    * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
8
    * Neither the name of the author nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
9
 
10
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
11
*/
12
 
13
//----------------------------------------------------------------------
14
//  Author: Guy Hutchison
15
//
16
//  Memory Controller/Arbiter
17
//----------------------------------------------------------------------
18
 
19
module lcfg_memctl
20
  (/*AUTOARG*/
21
  // Outputs
22
  a_wait_n, a_rdata, b_wait_n, b_rdata, cfgi_trdy, cfgi_rd_data,
23
  // Inputs
24
  clk, reset_n, a_mreq_n, a_rd_n, a_wr_n, a_addr, a_wdata, b_mreq_n,
25
  b_wr_n, b_addr, b_wdata, lcfg_init, cfgi_irdy, cfgi_addr,
26 105 ghutchis
  cfgi_write, cfgi_wr_data
27 101 ghutchis
  );
28
 
29 105 ghutchis
  // address size of memory
30
  parameter mem_asz = 13, mem_depth = 8192;
31
 
32 101 ghutchis
  input         clk;
33
  input         reset_n;
34
 
35
  // read port A (uP)
36
  input         a_mreq_n;
37
  input         a_rd_n;
38
  input         a_wr_n;
39 105 ghutchis
  input [mem_asz+1:0]  a_addr;
40 101 ghutchis
  output        a_wait_n;
41
  input [7:0]   a_wdata;
42
  output [7:0]  a_rdata;
43
  reg           a_wait_n;
44
 
45
  // read port B
46
  input         b_mreq_n;
47
  input         b_wr_n;
48 105 ghutchis
  input [mem_asz-1:0]  b_addr;
49 101 ghutchis
  output        b_wait_n;
50
  input [31:0]  b_wdata;
51
  output [31:0] b_rdata;
52
  reg           b_wait_n;
53
 
54
  input         lcfg_init;
55
 
56
  // incoming config interface to 
57
  // read/write processor memory
58
  input         cfgi_irdy;
59
  output     cfgi_trdy;
60 105 ghutchis
  input [mem_asz-1:0] cfgi_addr;
61 101 ghutchis
  input         cfgi_write;
62
  input [31:0]  cfgi_wr_data;
63
  output [31:0] cfgi_rd_data;
64
  reg           cfgi_trdy, nxt_cfgi_trdy;
65
 
66
  reg           ram_nwrt;
67
  reg           ram_nce;
68
  reg [31:0]    ram_din;
69 105 ghutchis
  reg [mem_asz-1:0]    ram_addr;
70 101 ghutchis
  wire [31:0]   dout;
71
  reg [7:0]     a_rdata;
72
 
73 105 ghutchis
  reg [mem_asz-1:0]    ca_addr, nxt_ca_addr;
74 101 ghutchis
  reg [31:0]    ca_data, nxt_ca_data;
75 105 ghutchis
  reg [mem_asz-1:0]    wc_addr, nxt_wc_addr;
76 101 ghutchis
  reg [31:0]    wc_data, nxt_wc_data;
77
  reg           cvld, nxt_cvld;
78
  reg           wcvld, nxt_wcvld;
79
 
80
  reg           a_prio, nxt_a_prio;
81
  reg           a_rip, nxt_a_rip;  // read in progress by A
82
  reg           a_wip, nxt_a_wip;  // write (read-cache-fill) in progress by A
83
  reg           b_rip, nxt_b_rip;  // read in progress by B
84 103 ghutchis
  wire          c_rip = cfgi_trdy;
85 105 ghutchis
  wire          c_rip = cfgi_trdy;
86 101 ghutchis
  wire          a_cache_hit, b_cache_hit;
87
 
88
  /*AUTOWIRE*/
89
 
90 105 ghutchis
/* -----\/----- EXCLUDED -----\/-----
91 101 ghutchis
  assign #1     t_ram_nwrt = ram_nwrt;
92
  assign #1     t_ram_nce = ram_nce;
93
  assign #1     t_ram_addr = ram_addr;
94
  assign #1     t_ram_din = ram_din;
95 105 ghutchis
 -----/\----- EXCLUDED -----/\----- */
96 101 ghutchis
 
97 105 ghutchis
  assign        cfgi_rd_data = dout;
98 101 ghutchis
  assign        b_rdata = dout;
99
 
100 105 ghutchis
  assign a_cache_hit = cvld & (ca_addr == a_addr[mem_asz+1:2]);
101
  assign b_cache_hit = wcvld & (wc_addr == a_addr[mem_asz+1:2]);
102 101 ghutchis
 
103
 
104
  /* behave1p_mem AUTO_TEMPLATE
105
   (
106
   // Outputs
107 105 ghutchis
   .d_out                              (dout),
108 101 ghutchis
   // Inputs
109 105 ghutchis
   .wr_en                             (!ram_nce & !ram_nwrt),
110
   .rd_en                             (!ram_nce & ram_nwrt),
111
   .clk                               (clk),
112
   .d_in                               (ram_din[]),
113
   .addr                                (ram_addr[]),
114 101 ghutchis
   );
115
   */
116
 
117
  behave1p_mem #(.width(32),
118 105 ghutchis
                 .depth (mem_depth),
119
                 .addr_sz (mem_asz))  mem
120 101 ghutchis
    (/*AUTOINST*/
121
     // Outputs
122 105 ghutchis
     .d_out                             (dout),                  // Templated
123 101 ghutchis
     // Inputs
124 105 ghutchis
     .wr_en                             (!ram_nce & !ram_nwrt),  // Templated
125
     .rd_en                             (!ram_nce & ram_nwrt),   // Templated
126 101 ghutchis
     .clk                               (clk),                   // Templated
127 105 ghutchis
     .d_in                              (ram_din[31:0]),         // Templated
128
     .addr                              (ram_addr[(mem_asz)-1:0])); // Templated
129 101 ghutchis
 
130
  always @*
131
    begin
132
      nxt_ca_addr = ca_addr;
133
      ram_nwrt = 1;
134
      ram_nce  = 1;
135
      ram_din = 32'h0;
136 105 ghutchis
      ram_addr = a_addr[mem_asz+1:2];
137 101 ghutchis
      a_wait_n = 1;
138
      b_wait_n = 1;
139
      nxt_a_prio = a_prio;
140
      nxt_a_rip  = 0;
141
      nxt_b_rip  = 0;
142
      nxt_a_wip  = a_wip;
143
      nxt_ca_data = ca_data;
144
      nxt_cvld    = cvld;
145
      nxt_wcvld   = wcvld;
146
      nxt_wc_data = wc_data;
147
      nxt_wc_addr = wc_addr;
148
      nxt_cfgi_trdy = 0;
149
 
150
      if (a_cache_hit)
151
        begin
152
          case (a_addr[1:0])
153
 
154
            1 : a_rdata = ca_data[15:8];
155
            2 : a_rdata = ca_data[23:16];
156
            3 : a_rdata = ca_data[31:24];
157
          endcase // case(a_addr[1:0])
158
        end
159
      else if (b_cache_hit)
160
        begin
161
          case (a_addr[1:0])
162
 
163
            1 : a_rdata = wc_data[15:8];
164
            2 : a_rdata = wc_data[23:16];
165
            3 : a_rdata = wc_data[31:24];
166
          endcase // case(a_addr[1:0])
167
        end
168
      else
169
        a_rdata = 0;
170
 
171
 
172
      if (lcfg_init)
173
        begin
174
          // repurpose the cache bits as FSM status bits
175
          // cvld == done
176
          if (!cvld)
177
            begin
178
              ram_nce    = 0;
179
              ram_addr = ca_addr;
180
              ram_nwrt = 0;
181
              ram_din = 32'h0;
182
              if (ca_addr == 8191)
183
                begin
184
                  nxt_ca_addr = ca_addr;
185
                  nxt_cvld = 1;
186
                  nxt_ca_data = 32'h0;
187
                end
188
              else
189
                nxt_ca_addr = ca_addr + 1;
190
            end
191
        end
192
      else
193
        begin
194
          if (!a_mreq_n)
195
            begin
196
              if (!a_rd_n)
197
                begin
198
                  // check for cache hit
199
                  if (!a_cache_hit & !b_cache_hit)
200
                    begin
201
                      a_wait_n   = 0;
202
                      if (a_rip)
203
                        begin
204 105 ghutchis
                          nxt_ca_addr = a_addr[mem_asz+1:2];
205 101 ghutchis
                          nxt_ca_data = dout;
206
                          nxt_cvld    = 1;
207
                        end
208
                      else if (a_prio | b_mreq_n)
209
                        begin
210 105 ghutchis
                          ram_addr = a_addr[mem_asz+1:2];
211 101 ghutchis
                          nxt_a_prio = 0;
212
                          ram_nce    = 0;
213
                          nxt_a_rip  = 1;
214
                        end
215
                    end // if (ca_addr != a_addr[14:2])
216
                end // if (!rd_n)
217
              else if (!a_wr_n)
218
                begin
219
                  if (a_prio | b_mreq_n)
220
                    begin
221
                      // if data is in our read cache, transfer it to the
222
                      // write cache, invalidate the read cache, update the
223
                      // appropriate data byte, and start the B cache
224
                      // write-back
225
                      if (a_cache_hit)
226
                        begin
227
                          nxt_cvld = 0;
228
 
229
                          case (a_addr[1:0])
230
 
231
                            1 : nxt_wc_data = { ca_data[31:16], a_wdata, ca_data[7:0] };
232
                            2 : nxt_wc_data = { ca_data[31:24], a_wdata, ca_data[15:0] };
233
                            3 : nxt_wc_data = { a_wdata, ca_data[23:0] };
234
                          endcase // case(a_addr[1:0])
235
                          nxt_wc_addr = ca_addr;
236
                          nxt_a_wip = 1;
237
                          nxt_a_prio = 1;
238
                        end
239
 
240
 
241
                      // if read is in progress, we have the results of our
242
                      // cache fill.  Store this in the write cache so next
243
                      // cycle we will get a cache hit.
244
                      else if (a_rip)
245
                        begin
246
                          a_wait_n    = 0;
247
                          nxt_wc_data = dout;
248 105 ghutchis
                          nxt_wc_addr = a_addr[mem_asz+1:2];
249 101 ghutchis
                          nxt_wcvld   = 1;
250
                        end
251
 
252
                      // if we get a write cache hit, we have the data we
253
                      // need.  Change the data in the write cache and trigger
254
                      // a write-back next cycle.
255
                      else if (b_cache_hit)
256
                        begin
257
                          case (a_addr[1:0])
258
 
259
                            1 : nxt_wc_data[15:8] = a_wdata;
260
                            2 : nxt_wc_data[23:16] = a_wdata;
261
                            3 : nxt_wc_data[31:24] = a_wdata;
262
                          endcase // case(a_addr[1:0])
263
                          nxt_a_wip = 1;
264
                          nxt_a_prio = 1;
265
                        end
266
 
267
                      // otherwise we do not have the data in our write cache
268
                      // yet.  Trigger a read to fill the write cache.
269
                      else if (a_prio | b_mreq_n)
270
                        begin
271
                          a_wait_n   = 0;
272 105 ghutchis
                          ram_addr = a_addr[mem_asz+1:2];
273 101 ghutchis
                          nxt_a_prio = 0;
274
                          ram_nce    = 0;
275
                          nxt_a_rip  = 1;
276
                        end
277
                    end
278
                  else
279
                    a_wait_n = 0;
280
                end
281
            end // if (!a_mreq_n)
282
          else
283
            begin
284
              if (a_wip & (a_prio|b_mreq_n))
285
                begin
286
                  ram_addr = wc_addr;
287
                  nxt_a_prio = 0;
288
                  ram_nce = 0;
289
                  ram_nwrt = 0;
290
                  nxt_a_wip = 0;
291
                  ram_din = wc_data;
292
                end
293
            end
294
 
295
 
296
          if (!b_mreq_n)
297
            begin
298
              if (!b_wr_n)
299
                begin
300
                  if (!a_prio | a_mreq_n)
301
                    begin
302
                      ram_addr = b_addr;
303
                      nxt_a_prio = 1;
304
                      ram_nce = 0;
305
                      ram_nwrt = 0;
306
                      ram_din = b_wdata;
307
                      if (b_addr == ca_addr)
308
                        nxt_cvld = 0;
309
                      if (wc_addr == ca_addr)
310
                        nxt_wcvld = 0;
311
                    end
312
                  else
313
                    b_wait_n = 0;
314
                end // if (!b_wr_n)
315
              else
316
                begin
317
                  if (b_rip)
318
                    begin
319
                      b_wait_n = 1;
320
                    end
321
                  else if (!a_prio | a_mreq_n)
322
                    begin
323
                      ram_addr = b_addr;
324
                      nxt_b_rip = 1;
325
                      nxt_a_prio = 1;
326
                      ram_nce = 0;
327
                      b_wait_n = 0;
328
                    end
329
                end
330
            end // if (!b_mreq_n)
331
 
332
          if (cfgi_irdy)
333
            begin
334
              if ((!a_mreq_n | !b_mreq_n) & !c_rip)
335
                begin
336
                  // access by A or B ports, stall until memory is free
337
                end
338
              else
339
                begin
340
                  if (cfgi_write & !cfgi_trdy)
341
                    begin
342
                      nxt_cfgi_trdy = 1;
343
                      ram_nce = 0;
344
                      ram_nwrt = 0;
345 105 ghutchis
                      ram_addr = cfgi_addr[mem_asz-1:0];
346 103 ghutchis
                      ram_din = cfgi_wr_data;
347 101 ghutchis
                      // invalidate caches as precaution
348
                      nxt_cvld = 0;
349
                      nxt_wcvld = 0;
350
                    end
351
                  else if (!cfgi_write & !cfgi_trdy)
352
                    begin
353
                      ram_nce = 0;
354 105 ghutchis
                      ram_addr = cfgi_addr[mem_asz-1:0];
355 101 ghutchis
                      nxt_cfgi_trdy = 1;
356
                    end
357
                end
358
            end
359
        end // if (lcfg_init)      
360
    end // always @ *
361
 
362
  always @(posedge clk or negedge reset_n)
363
    begin
364
      if (~reset_n)
365
        begin
366
          ca_addr <= 13'h0;
367
          cvld    <= #1 0;
368
          /*AUTORESET*/
369
          // Beginning of autoreset for uninitialized flops
370
          a_prio <= 1'h0;
371
          a_rip <= 1'h0;
372
          a_wip <= 1'h0;
373
          b_rip <= 1'h0;
374
          ca_data <= 32'h0;
375
          cfgi_trdy <= 1'h0;
376 105 ghutchis
          wc_addr <= {mem_asz{1'b0}};
377 101 ghutchis
          wc_data <= 32'h0;
378
          wcvld <= 1'h0;
379
          // End of automatics
380
        end
381
      else
382
        begin
383
          cvld    <= #1 nxt_cvld;
384
          ca_addr <= #1 nxt_ca_addr;
385
          ca_data <= #1 nxt_ca_data;
386
          wcvld   <= #1 nxt_wcvld;
387
          wc_addr <= #1 nxt_wc_addr;
388
          wc_data <= #1 nxt_wc_data;
389
          a_prio  <= #1 nxt_a_prio;
390
          a_rip   <= #1 nxt_a_rip;
391
          b_rip   <= #1 nxt_b_rip;
392
          a_wip   <= #1 nxt_a_wip;
393
          cfgi_trdy <= #1 nxt_cfgi_trdy;
394
        end
395
    end
396
 
397
endmodule // memcontrol
398
 
399
// Local Variables:
400
// verilog-library-files:(".")
401
// End:
402
 

powered by: WebSVN 2.1.0

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