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

Subversion Repositories mpeg2fpga

[/] [mpeg2fpga/] [trunk/] [bench/] [iverilog/] [mem_ctl.v] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 kdv
/*
2
 * mem_ctl.v
3
 *
4
 * Copyright (c) 2007 Koen De Vleeschauwer.
5
 *
6
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
7
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
8
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
9
 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
10
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
11
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
12
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
13
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
14
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
15
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
16
 * SUCH DAMAGE.
17
 */
18
 
19
/*
20
 * Dummy memory controller, used for simulation.
21
 * Useful as template for writing your own memory controller.
22
 */
23
 
24
`include "timescale.v"
25
 
26
`undef DEBUG
27
//`define DEBUG 1
28
 
29
// initialize memory
30
`undef MEMORY_INIT
31
//`define MAGIC_NUMBER 1
32
 
33
// write framestore to file 'framestore_000.ppm' every time current_frame changes
34
`undef DUMP_FRAMESTORE
35
`define DUMP_FRAMESTORE 1
36
 
37
// write framestore to file 'framestore_001.ppm' every 200 macroblocks. requires DUMP_FRAMESTORE.
38
`undef DUMP_FRAMESTORE_OFTEN
39
//`define DUMP_FRAMESTORE_OFTEN 1
40
 
41
module mem_ctl(
42
  clk, rst,
43
  mem_req_rd_cmd, mem_req_rd_addr, mem_req_rd_dta, mem_req_rd_en, mem_req_rd_valid,
44
  mem_res_wr_dta, mem_res_wr_en, mem_res_wr_almost_full
45
  );
46
 
47
  input            clk;
48
  input            rst;
49
  input       [1:0]mem_req_rd_cmd;
50
  input      [21:0]mem_req_rd_addr;
51
  input      [63:0]mem_req_rd_dta;
52
  output reg       mem_req_rd_en;
53
  input            mem_req_rd_valid;
54
  output reg [63:0]mem_res_wr_dta;
55
  output reg       mem_res_wr_en;
56
  input            mem_res_wr_almost_full;
57
 
58
`include "mem_codes.v"
59
 
60
  reg [63:0]mem[0:END_OF_MEM]; /* memory, 64-bit wide. Simulation only, not synthesizable. Size depends upon mpeg2 profile. Up to 32 mbyte large */
61
 
62
  always @(posedge clk)
63
    if (~rst) mem_req_rd_en <= 1'b0;
64
    else mem_req_rd_en <= ~mem_res_wr_almost_full;
65
 
66
  /* timing simulation: add #2 = 2 ns hold time to mem_res_wr_en and mem_res_wr_dta */
67
 
68
  always @(posedge clk)
69
    if (~rst) mem_res_wr_en <= #2 1'b0;
70
    else if (mem_req_rd_valid)
71
      case (mem_req_rd_cmd)
72
        CMD_NOOP:    mem_res_wr_en <= #2 1'b0;
73
        CMD_REFRESH: mem_res_wr_en <= #2 1'b0;
74
        CMD_READ:    mem_res_wr_en <= #2 1'b1;
75
        CMD_WRITE:   mem_res_wr_en <= #2 1'b0;
76
        default      mem_res_wr_en <= #2 1'b0;
77
      endcase
78
    else mem_res_wr_en <= #2 1'b0;
79
 
80
  /*
81
   * Memory read
82
   */
83
  always @(posedge clk)
84
    if (~rst) mem_res_wr_dta <= #2 63'b0;
85
    else if (mem_req_rd_valid)
86
      case (mem_req_rd_cmd)
87
        CMD_NOOP:    mem_res_wr_dta <= #2 63'b0;
88
        CMD_REFRESH: mem_res_wr_dta <= #2 63'b0;
89
        CMD_READ:    mem_res_wr_dta <= #2 mem[mem_req_rd_addr];
90
        CMD_WRITE:   mem_res_wr_dta <= #2 63'b0;
91
        default      mem_res_wr_dta <= #2 63'b0;
92
      endcase
93
    else mem_res_wr_dta <= #2 63'b0;
94
 
95
  /*
96
   * Memory write
97
   */
98
  always @(posedge clk)
99
    if (mem_req_rd_valid && (mem_req_rd_cmd == CMD_WRITE)) mem[mem_req_rd_addr] <= mem_req_rd_dta;
100
 
101
  /*
102
   * Trap error address
103
   */
104
  always @(posedge clk)
105
    if (mem_req_rd_valid && ((mem_req_rd_cmd == CMD_WRITE) || (mem_req_rd_cmd == CMD_READ))
106
                         && (mem_req_rd_addr == ADDR_ERR))
107
                         begin
108
                           $display("%m *** error: access to ADDR_ERR ***");
109
`ifdef DUMP_FRAMESTORE
110
                           write_framestore;
111
`endif
112
                           //$stop;
113
                         end
114
 
115
 
116
`ifdef DEBUG
117
  always @(posedge clk)
118
    if (mem_req_rd_valid)
119
      case (mem_req_rd_cmd)
120
        CMD_NOOP:    #0 $display("%m\tCMD_NOOP    ");
121
        CMD_REFRESH: #0 $display("%m\tCMD_REFRESH ");
122
        CMD_READ:    #0 $display("%m\tCMD_READ    mem[%6h] : %h", mem_req_rd_addr, mem[mem_req_rd_addr]);
123
        CMD_WRITE:   #0 $display("%m\tCMD_WRITE   mem[%6h] = %h", mem_req_rd_addr, mem_req_rd_dta);
124
        default      #0 $display("%m\t*** Error: unknown command %d ***", mem_req_rd_cmd);
125
      endcase
126
 
127
`endif
128
 
129
`ifdef MEMORY_INIT
130
  /*
131
   Initialize memory at powerup. Optional.
132
   */
133
 
134
  integer addr;
135
 
136
  initial
137
    begin
138
      for ( addr = 0; addr < END_OF_MEM; addr = addr + 1)
139
        mem[addr] = {8{8'd128}}; // initialize memory to all zeroes in yuv; all zeroes in yuv is a dull green
140
    end
141
`endif
142
 
143
  /*
144
    write all of memory to stdout
145
   */
146
 
147
  task mem_dump;
148
  /*
149
   * Dump memory.
150
   * Used in testbench.
151
   */
152
  integer mem_dump;
153
 
154
    begin
155
      $display("%m\t\tmemory dump: begin");
156
      for (mem_dump = 22'h0; mem_dump <= 22'h3fffff; mem_dump = mem_dump + 1)
157
        if (mem[mem_dump] !== 64'bx)
158
          begin
159
            $display("%m\t\tmemory dump: %5h: %8h", mem_dump, mem[mem_dump]);
160
          end
161
      $display("%m\t\tmemory dump: end");
162
    end
163
  endtask
164
 
165
`ifdef DUMP_FRAMESTORE
166
 
167
  wire [13:0]width;
168
  wire [13:0]height;
169
  reg  [13:0]mb_width;
170
  reg  [13:0]mb_height;
171
  wire [13:0]display_horizontal_size;
172
  wire [13:0]display_vertical_size;
173
  wire  [1:0]picture_structure;
174
  wire  [1:0]chroma_format;
175
  wire       update_picture_buffers;
176
  wire [12:0]macroblock_address;
177
 
178
  assign width                   = testbench.mpeg2.vld.horizontal_size;
179
  assign height                  = testbench.mpeg2.vld.vertical_size;
180
  assign display_horizontal_size = testbench.mpeg2.vld.display_horizontal_size;
181
  assign display_vertical_size   = testbench.mpeg2.vld.display_vertical_size;
182
  assign picture_structure       = testbench.mpeg2.vld.picture_structure;
183
  assign chroma_format           = testbench.mpeg2.vld.chroma_format;
184
  assign update_picture_buffers  = testbench.mpeg2.update_picture_buffers;
185
  assign macroblock_address      = testbench.mpeg2.macroblock_address;
186
 
187
  always @*
188
    begin
189
      mb_width  <= (width  + 15) >> 4;
190
      mb_height <= (height + 15) >> 4;
191
    end
192
 
193
  /*
194
   * count frames
195
   */
196
 
197
  integer frame_number = 0;
198
 
199
  always @(posedge update_picture_buffers)
200
    frame_number <= frame_number + 1;
201
 
202
  /*
203
   * Create a bitmap file of the framestore.  Bitmap is in Portable Pixmap format (ppm).
204
   * This is a task used in debugging.
205
   */
206
 
207
  reg [31:0]fname_cnt = "0000";
208
 
209
  task write_framestore;
210
 
211
    reg [32*8:1]fname;
212
    integer fp;
213
    integer w;
214
    integer h;
215
 
216
    `include "vld_codes.v"
217
 
218
    begin
219
      if ((^mb_width !== 1'bx) && (^mb_height !== 1'bx)) // check image size valid
220
        begin
221
          /* new filename */
222
          fname = {"framestore_", fname_cnt, ".ppm"};
223
          /* implement a counter for string "fname_cnt" */
224
          if (fname_cnt[7:0] != "9")
225
            fname_cnt[7:0] = fname_cnt[7:0] + 1;
226
          else
227
            begin
228
              fname_cnt[7:0] = "0";
229
              if (fname_cnt[15:8] != "9")
230
                fname_cnt[15:8] = fname_cnt[15:8] + 1;
231
              else
232
                begin
233
                  fname_cnt[15:8] = "0";
234
                  if (fname_cnt[23:16] != "9")
235
                    fname_cnt[23:16] = fname_cnt[23:16] + 1;
236
                  else
237
                    begin
238
                      fname_cnt[23:16] = "0";
239
                      if (fname_cnt[31:24] != "9")
240
                        fname_cnt[31:24] = fname_cnt[31:24] + 1;
241
                      else
242
                        fname_cnt[31:24] = "0";
243
                    end
244
                end
245
            end
246
          // open new file
247
          fp=$fopen(fname, "w");
248
          if (fp == 0)
249
            begin
250
              $display ("%m\t*** error opening file ***");
251
              $finish;
252
            end
253
          $fwrite(fp, "P3\n"); // Portable pixmap, ascii.
254
          $timeformat(-3, 2, " ms", 8);
255
          $fwrite(fp, "# mpeg2 framestore dump @ %t\n", $time);
256
          $display("%m\tdumping framestore to %s @ %t", fname, $time);
257
          $timeformat(-9, 2, " ns", 20);
258
          $fwrite(fp, "# frame number %d\n", frame_number);
259
          $fwrite(fp, "# horizontal_size %d\n", width);
260
          $fwrite(fp, "# vertical_size %d\n", height);
261
          $fwrite(fp, "# display_horizontal_size %d\n", display_horizontal_size);
262
          $fwrite(fp, "# display_vertical_size %d\n", display_vertical_size);
263
          $fwrite(fp, "# mb_width %d\n", mb_width);
264
          $fwrite(fp, "# mb_height %d\n", mb_height);
265
          if (picture_structure==FRAME_PICTURE)
266
            $fwrite(fp, "# picture_structure frame picture\n");
267
          else
268
            $fwrite(fp, "# picture_structure field picture\n");
269
 
270
          if (chroma_format == CHROMA420)
271
            $fwrite(fp, "# chroma_format 4:2:0\n");
272
          else
273
            $fwrite(fp, "# chroma_format %d\n", chroma_format);
274
 
275
          $fwrite(fp, "%d %d 255\n", width, height * 9 + 26);
276
 
277
          write_mb (fp, 4, FRAME_0_Y,  mb_width, mb_height);
278
          write_mb (fp, 1, FRAME_0_CR, mb_width, mb_height);
279
          write_mb (fp, 1, FRAME_0_CB, mb_width, mb_height);
280
 
281
          write_mb (fp, 4, FRAME_1_Y,  mb_width, mb_height);
282
          write_mb (fp, 1, FRAME_1_CR, mb_width, mb_height);
283
          write_mb (fp, 1, FRAME_1_CB, mb_width, mb_height);
284
 
285
          write_mb (fp, 4, FRAME_2_Y,  mb_width, mb_height);
286
          write_mb (fp, 1, FRAME_2_CR, mb_width, mb_height);
287
          write_mb (fp, 1, FRAME_2_CB, mb_width, mb_height);
288
 
289
          write_mb (fp, 4, FRAME_3_Y,  mb_width, mb_height);
290
          write_mb (fp, 1, FRAME_3_CR, mb_width, mb_height);
291
          write_mb (fp, 1, FRAME_3_CB, mb_width, mb_height);
292
 
293
          write_mb (fp, 4, OSD,        mb_width, mb_height);
294
          $fwrite(fp, "# not truncated\n");
295
          $fclose(fp);
296
        end
297
    end
298
  endtask
299
 
300
  task write_mb;
301
 
302
    input [31:0]fp;            // file pointer to write to 
303
    input  [2:0]blocks;        // blocks per macroblock
304
    input [21:0]base_address;  // base address of lumi/chromi region in memory
305
    input [15:0]mb_width;      // width in macroblocks
306
    input [15:0]mb_height;     // height in macroblocks
307
 
308
    reg [63:0]row;
309
 
310
    reg  [7:0]pixel_0;
311
    reg  [7:0]pixel_1;
312
    reg  [7:0]pixel_2;
313
    reg  [7:0]pixel_3;
314
    reg  [7:0]pixel_4;
315
    reg  [7:0]pixel_5;
316
    reg  [7:0]pixel_6;
317
    reg  [7:0]pixel_7;
318
 
319
    integer   fp;
320
    integer   h;
321
    integer   f;
322
    integer   r;
323
    integer   s;
324
    integer   w;
325
    reg [21:0]addr;
326
 
327
    begin
328
      /* white separator line */
329
      for (w = 0; w < 2 * mb_width; w = w + 1)
330
        begin
331
          for (s = 0; s < 24; s = s + 1)
332
            $fwrite(fp, " 255");
333
          $fwrite(fp, "\n");
334
        end
335
      /* this code needs to be kept synchronized to memory_address */
336
      addr = base_address;
337
      case (blocks)
338
        4:
339
          for (h = 0; h < 16 * mb_height; h = h + 1)
340
            begin
341
              for (w = 0; w < 2 * mb_width; w = w + 1)
342
                begin
343
                  write_row (fp, addr); /* block 0 */
344
                  addr = addr + 1;
345
                end
346
            end
347
        1:
348
          for (h = 0; h < 8 * mb_height; h = h + 1)
349
            begin
350
              for (w = 0; w < mb_width; w = w + 1)
351
                begin
352
                  write_row (fp, addr); /* block 0 */
353
                  addr = addr + 1;
354
                end
355
              for (w = 0; w < mb_width; w = w + 1)
356
                begin
357
                  for (s = 0; s < 24; s = s + 1)
358
                    $fwrite(fp, " 255");
359
                  $fwrite(fp, "\n");
360
                end
361
            end
362
        default
363
            begin
364
              $display("%m\tchroma format not implemented\n");
365
            end
366
      endcase
367
      /* white separator line */
368
      for (w = 0; w < 2 * mb_width; w = w + 1)
369
        begin
370
          for (s = 0; s < 24; s = s + 1)
371
            $fwrite(fp, " 255");
372
          $fwrite(fp, "\n");
373
        end
374
    end
375
  endtask
376
 
377
  task write_row;
378
 
379
    input [31:0]fp;       // file pointer to write to 
380
    input [21:0]address;  // address of block row
381
 
382
    reg  [63:0]dta;
383
 
384
    integer     fp;
385
 
386
    reg  signed [7:0]pixel_0;
387
    reg  signed [7:0]pixel_1;
388
    reg  signed [7:0]pixel_2;
389
    reg  signed [7:0]pixel_3;
390
    reg  signed [7:0]pixel_4;
391
    reg  signed [7:0]pixel_5;
392
    reg  signed [7:0]pixel_6;
393
    reg  signed [7:0]pixel_7;
394
 
395
    reg  signed [8:0]pixval_0;
396
    reg  signed [8:0]pixval_1;
397
    reg  signed [8:0]pixval_2;
398
    reg  signed [8:0]pixval_3;
399
    reg  signed [8:0]pixval_4;
400
    reg  signed [8:0]pixval_5;
401
    reg  signed [8:0]pixval_6;
402
    reg  signed [8:0]pixval_7;
403
 
404
 
405
    begin
406
      dta = mem[address];
407
 
408
      {pixel_0, pixel_1, pixel_2, pixel_3, pixel_4, pixel_5, pixel_6, pixel_7} = dta;
409
 
410
      pixval_0 = {pixel_0[7], pixel_0};
411
      pixval_1 = {pixel_1[7], pixel_1};
412
      pixval_2 = {pixel_2[7], pixel_2};
413
      pixval_3 = {pixel_3[7], pixel_3};
414
      pixval_4 = {pixel_4[7], pixel_4};
415
      pixval_5 = {pixel_5[7], pixel_5};
416
      pixval_6 = {pixel_6[7], pixel_6};
417
      pixval_7 = {pixel_7[7], pixel_7};
418
 
419
      pixval_0 = pixval_0 + 9'sd128;
420
      pixval_1 = pixval_1 + 9'sd128;
421
      pixval_2 = pixval_2 + 9'sd128;
422
      pixval_3 = pixval_3 + 9'sd128;
423
      pixval_4 = pixval_4 + 9'sd128;
424
      pixval_5 = pixval_5 + 9'sd128;
425
      pixval_6 = pixval_6 + 9'sd128;
426
      pixval_7 = pixval_7 + 9'sd128;
427
 
428
      /* check for undefined pixels, replace with green to draw attention */
429
      if (^pixval_0 === 1'bx) $fwrite(fp, "   0  127    0 "); else $fwrite(fp, "%4d %4d %4d ", pixval_0, pixval_0, pixval_0);
430
      if (^pixval_1 === 1'bx) $fwrite(fp, "   0  127    0 "); else $fwrite(fp, "%4d %4d %4d ", pixval_1, pixval_1, pixval_1);
431
      if (^pixval_2 === 1'bx) $fwrite(fp, "   0  127    0 "); else $fwrite(fp, "%4d %4d %4d ", pixval_2, pixval_2, pixval_2);
432
      if (^pixval_3 === 1'bx) $fwrite(fp, "   0  127    0 "); else $fwrite(fp, "%4d %4d %4d ", pixval_3, pixval_3, pixval_3);
433
      if (^pixval_4 === 1'bx) $fwrite(fp, "   0  127    0 "); else $fwrite(fp, "%4d %4d %4d ", pixval_4, pixval_4, pixval_4);
434
      if (^pixval_5 === 1'bx) $fwrite(fp, "   0  127    0 "); else $fwrite(fp, "%4d %4d %4d ", pixval_5, pixval_5, pixval_5);
435
      if (^pixval_6 === 1'bx) $fwrite(fp, "   0  127    0 "); else $fwrite(fp, "%4d %4d %4d ", pixval_6, pixval_6, pixval_6);
436
      if (^pixval_7 === 1'bx) $fwrite(fp, "   0  127    0 "); else $fwrite(fp, "%4d %4d %4d ", pixval_7, pixval_7, pixval_7);
437
//      $fwrite(fp, "# mem[%6h]: %8h", address, dta); /* Some ppm picture viewers do not accept comment in mid-image */
438
      $fwrite(fp, "\n");
439
 
440
    end
441
  endtask
442
 
443
`ifndef DUMP_FRAMESTORE_OFTEN
444
  /* trigger framestore dump when updating picture buffers */
445
 
446
/*
447
  always @(posedge update_picture_buffers)
448
    write_framestore;
449
*/
450
 
451
  always @(posedge clk)
452
    if (mem_req_rd_valid && (mem_req_rd_cmd == CMD_WRITE)
453
                         && ((mem_req_rd_addr == FRAME_0_Y) || (mem_req_rd_addr == FRAME_1_Y) || (mem_req_rd_addr == FRAME_2_Y) || (mem_req_rd_addr == FRAME_3_Y)))
454
      write_framestore;
455
`endif
456
 
457
`ifdef DUMP_FRAMESTORE_OFTEN
458
  /* trigger framestore dump every 200 macroblocks */
459
  always @(macroblock_address)
460
    if ((^macroblock_address !== 1'bx) && (macroblock_address % 200) == 0) write_framestore;
461
`endif
462
 
463
  always @(macroblock_address)
464
    if (^macroblock_address !== 1'bx)
465
      $strobe("%m\tmacroblock_address: %d", macroblock_address);
466
 
467
`endif
468
 
469
endmodule
470
/* not truncated */

powered by: WebSVN 2.1.0

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