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

Subversion Repositories tv80

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

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

powered by: WebSVN 2.1.0

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