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

Subversion Repositories tv80

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

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

powered by: WebSVN 2.1.0

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