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

Subversion Repositories tv80

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

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 101 ghutchis
  wire          a_cache_hit, b_cache_hit;
86
 
87
  /*AUTOWIRE*/
88
 
89 105 ghutchis
  assign        cfgi_rd_data = dout;
90 101 ghutchis
  assign        b_rdata = dout;
91
 
92 105 ghutchis
  assign a_cache_hit = cvld & (ca_addr == a_addr[mem_asz+1:2]);
93
  assign b_cache_hit = wcvld & (wc_addr == a_addr[mem_asz+1:2]);
94 101 ghutchis
 
95
 
96
  /* behave1p_mem AUTO_TEMPLATE
97
   (
98
   // Outputs
99 105 ghutchis
   .d_out                              (dout),
100 101 ghutchis
   // Inputs
101 105 ghutchis
   .wr_en                             (!ram_nce & !ram_nwrt),
102
   .rd_en                             (!ram_nce & ram_nwrt),
103
   .clk                               (clk),
104
   .d_in                               (ram_din[]),
105
   .addr                                (ram_addr[]),
106 101 ghutchis
   );
107
   */
108
 
109
  behave1p_mem #(.width(32),
110 105 ghutchis
                 .depth (mem_depth),
111
                 .addr_sz (mem_asz))  mem
112 101 ghutchis
    (/*AUTOINST*/
113
     // Outputs
114 105 ghutchis
     .d_out                             (dout),                  // Templated
115 101 ghutchis
     // Inputs
116 105 ghutchis
     .wr_en                             (!ram_nce & !ram_nwrt),  // Templated
117
     .rd_en                             (!ram_nce & ram_nwrt),   // Templated
118 101 ghutchis
     .clk                               (clk),                   // Templated
119 105 ghutchis
     .d_in                              (ram_din[31:0]),         // Templated
120
     .addr                              (ram_addr[(mem_asz)-1:0])); // Templated
121 101 ghutchis
 
122
  always @*
123
    begin
124
      nxt_ca_addr = ca_addr;
125
      ram_nwrt = 1;
126
      ram_nce  = 1;
127
      ram_din = 32'h0;
128 105 ghutchis
      ram_addr = a_addr[mem_asz+1:2];
129 101 ghutchis
      a_wait_n = 1;
130
      b_wait_n = 1;
131
      nxt_a_prio = a_prio;
132
      nxt_a_rip  = 0;
133
      nxt_b_rip  = 0;
134
      nxt_a_wip  = a_wip;
135
      nxt_ca_data = ca_data;
136
      nxt_cvld    = cvld;
137
      nxt_wcvld   = wcvld;
138
      nxt_wc_data = wc_data;
139
      nxt_wc_addr = wc_addr;
140
      nxt_cfgi_trdy = 0;
141
 
142
      if (a_cache_hit)
143
        begin
144
          case (a_addr[1:0])
145
 
146
            1 : a_rdata = ca_data[15:8];
147
            2 : a_rdata = ca_data[23:16];
148
            3 : a_rdata = ca_data[31:24];
149
          endcase // case(a_addr[1:0])
150
        end
151
      else if (b_cache_hit)
152
        begin
153
          case (a_addr[1:0])
154
 
155
            1 : a_rdata = wc_data[15:8];
156
            2 : a_rdata = wc_data[23:16];
157
            3 : a_rdata = wc_data[31:24];
158
          endcase // case(a_addr[1:0])
159
        end
160
      else
161
        a_rdata = 0;
162
 
163
 
164
      if (lcfg_init)
165
        begin
166
          // repurpose the cache bits as FSM status bits
167
          // cvld == done
168
          if (!cvld)
169
            begin
170
              ram_nce    = 0;
171
              ram_addr = ca_addr;
172
              ram_nwrt = 0;
173
              ram_din = 32'h0;
174
              if (ca_addr == 8191)
175
                begin
176
                  nxt_ca_addr = ca_addr;
177
                  nxt_cvld = 1;
178
                  nxt_ca_data = 32'h0;
179
                end
180
              else
181
                nxt_ca_addr = ca_addr + 1;
182
            end
183
        end
184
      else
185
        begin
186
          if (!a_mreq_n)
187
            begin
188
              if (!a_rd_n)
189
                begin
190
                  // check for cache hit
191
                  if (!a_cache_hit & !b_cache_hit)
192
                    begin
193
                      a_wait_n   = 0;
194
                      if (a_rip)
195
                        begin
196 105 ghutchis
                          nxt_ca_addr = a_addr[mem_asz+1:2];
197 101 ghutchis
                          nxt_ca_data = dout;
198
                          nxt_cvld    = 1;
199
                        end
200
                      else if (a_prio | b_mreq_n)
201
                        begin
202 105 ghutchis
                          ram_addr = a_addr[mem_asz+1:2];
203 101 ghutchis
                          nxt_a_prio = 0;
204
                          ram_nce    = 0;
205
                          nxt_a_rip  = 1;
206
                        end
207
                    end // if (ca_addr != a_addr[14:2])
208
                end // if (!rd_n)
209
              else if (!a_wr_n)
210
                begin
211
                  if (a_prio | b_mreq_n)
212
                    begin
213
                      // if data is in our read cache, transfer it to the
214
                      // write cache, invalidate the read cache, update the
215
                      // appropriate data byte, and start the B cache
216
                      // write-back
217
                      if (a_cache_hit)
218
                        begin
219
                          nxt_cvld = 0;
220
 
221
                          case (a_addr[1:0])
222
 
223
                            1 : nxt_wc_data = { ca_data[31:16], a_wdata, ca_data[7:0] };
224
                            2 : nxt_wc_data = { ca_data[31:24], a_wdata, ca_data[15:0] };
225
                            3 : nxt_wc_data = { a_wdata, ca_data[23:0] };
226
                          endcase // case(a_addr[1:0])
227
                          nxt_wc_addr = ca_addr;
228
                          nxt_a_wip = 1;
229
                          nxt_a_prio = 1;
230
                        end
231
 
232
 
233
                      // if read is in progress, we have the results of our
234
                      // cache fill.  Store this in the write cache so next
235
                      // cycle we will get a cache hit.
236
                      else if (a_rip)
237
                        begin
238
                          a_wait_n    = 0;
239
                          nxt_wc_data = dout;
240 105 ghutchis
                          nxt_wc_addr = a_addr[mem_asz+1:2];
241 101 ghutchis
                          nxt_wcvld   = 1;
242
                        end
243
 
244
                      // if we get a write cache hit, we have the data we
245
                      // need.  Change the data in the write cache and trigger
246
                      // a write-back next cycle.
247
                      else if (b_cache_hit)
248
                        begin
249
                          case (a_addr[1:0])
250
 
251
                            1 : nxt_wc_data[15:8] = a_wdata;
252
                            2 : nxt_wc_data[23:16] = a_wdata;
253
                            3 : nxt_wc_data[31:24] = a_wdata;
254
                          endcase // case(a_addr[1:0])
255
                          nxt_a_wip = 1;
256
                          nxt_a_prio = 1;
257
                        end
258
 
259
                      // otherwise we do not have the data in our write cache
260
                      // yet.  Trigger a read to fill the write cache.
261
                      else if (a_prio | b_mreq_n)
262
                        begin
263
                          a_wait_n   = 0;
264 105 ghutchis
                          ram_addr = a_addr[mem_asz+1:2];
265 101 ghutchis
                          nxt_a_prio = 0;
266
                          ram_nce    = 0;
267
                          nxt_a_rip  = 1;
268
                        end
269
                    end
270
                  else
271
                    a_wait_n = 0;
272
                end
273
            end // if (!a_mreq_n)
274
          else
275
            begin
276
              if (a_wip & (a_prio|b_mreq_n))
277
                begin
278
                  ram_addr = wc_addr;
279
                  nxt_a_prio = 0;
280
                  ram_nce = 0;
281
                  ram_nwrt = 0;
282
                  nxt_a_wip = 0;
283
                  ram_din = wc_data;
284
                end
285
            end
286
 
287
 
288
          if (!b_mreq_n)
289
            begin
290
              if (!b_wr_n)
291
                begin
292
                  if (!a_prio | a_mreq_n)
293
                    begin
294
                      ram_addr = b_addr;
295
                      nxt_a_prio = 1;
296
                      ram_nce = 0;
297
                      ram_nwrt = 0;
298
                      ram_din = b_wdata;
299
                      if (b_addr == ca_addr)
300
                        nxt_cvld = 0;
301
                      if (wc_addr == ca_addr)
302
                        nxt_wcvld = 0;
303
                    end
304
                  else
305
                    b_wait_n = 0;
306
                end // if (!b_wr_n)
307
              else
308
                begin
309
                  if (b_rip)
310
                    begin
311
                      b_wait_n = 1;
312
                    end
313
                  else if (!a_prio | a_mreq_n)
314
                    begin
315
                      ram_addr = b_addr;
316
                      nxt_b_rip = 1;
317
                      nxt_a_prio = 1;
318
                      ram_nce = 0;
319
                      b_wait_n = 0;
320
                    end
321
                end
322
            end // if (!b_mreq_n)
323
 
324
          if (cfgi_irdy)
325
            begin
326 107 ghutchis
              if ((a_mreq_n & b_mreq_n) & !c_rip & !a_wip)
327 101 ghutchis
                begin
328
                  if (cfgi_write & !cfgi_trdy)
329
                    begin
330
                      nxt_cfgi_trdy = 1;
331
                      ram_nce = 0;
332
                      ram_nwrt = 0;
333 105 ghutchis
                      ram_addr = cfgi_addr[mem_asz-1:0];
334 103 ghutchis
                      ram_din = cfgi_wr_data;
335 101 ghutchis
                      // invalidate caches as precaution
336
                      nxt_cvld = 0;
337
                      nxt_wcvld = 0;
338
                    end
339
                  else if (!cfgi_write & !cfgi_trdy)
340
                    begin
341
                      ram_nce = 0;
342 105 ghutchis
                      ram_addr = cfgi_addr[mem_asz-1:0];
343 101 ghutchis
                      nxt_cfgi_trdy = 1;
344
                    end
345
                end
346
            end
347
        end // if (lcfg_init)      
348
    end // always @ *
349
 
350
  always @(posedge clk or negedge reset_n)
351
    begin
352
      if (~reset_n)
353
        begin
354
          ca_addr <= 13'h0;
355 107 ghutchis
          cvld    <= 0;
356 101 ghutchis
          /*AUTORESET*/
357
          // Beginning of autoreset for uninitialized flops
358
          a_prio <= 1'h0;
359
          a_rip <= 1'h0;
360
          a_wip <= 1'h0;
361
          b_rip <= 1'h0;
362
          ca_data <= 32'h0;
363
          cfgi_trdy <= 1'h0;
364 105 ghutchis
          wc_addr <= {mem_asz{1'b0}};
365 101 ghutchis
          wc_data <= 32'h0;
366
          wcvld <= 1'h0;
367
          // End of automatics
368
        end
369
      else
370
        begin
371 107 ghutchis
          cvld    <= nxt_cvld;
372
          ca_addr <= nxt_ca_addr;
373
          ca_data <= nxt_ca_data;
374
          wcvld   <= nxt_wcvld;
375
          wc_addr <= nxt_wc_addr;
376
          wc_data <= nxt_wc_data;
377
          a_prio  <= nxt_a_prio;
378
          a_rip   <= nxt_a_rip;
379
          b_rip   <= nxt_b_rip;
380
          a_wip   <= nxt_a_wip;
381
          cfgi_trdy <= nxt_cfgi_trdy;
382 101 ghutchis
        end
383
    end
384
 
385
endmodule // memcontrol
386
 
387
// Local Variables:
388
// verilog-library-files:(".")
389
// End:
390
 

powered by: WebSVN 2.1.0

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