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

Subversion Repositories mpeg2fpga

[/] [mpeg2fpga/] [trunk/] [bench/] [iverilog/] [testbench.v] - Rev 2

Compare with Previous | Blame | View Log

/* 
 * testbench.v
 * 
 * Copyright (c) 2007 Koen De Vleeschauwer. 
 * 
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
 *
 */
 
/*
 * testbench - mpeg2 decoder test bench
 */
 
`include "timescale.v"
 
/* max number of bytes in stream.dat mpeg2 stream */
`define MAX_STREAM_LENGTH 4194304
 
/* clk at 75 MHz */
`define CLK_PERIOD 13.3
 
/* mem_clk at 125 MHz */
`define MEMCLK_PERIOD 8.0
 
/* dot_clk at 27 MHz */
`define VIDCLK_PERIOD 37.0
 
`undef DEBUG
//`define DEBUG 1
 
/* write (lxt) dumpfile of simulation run */
`undef DEBUG_DUMP
`define DEBUG_DUMP 1
 
// write rgb+sync output to file tvout_0.ppm or tv_out_1.ppm, alternately.
`undef DUMP_TVOUT
`define DUMP_TVOUT 1
 
module testbench();
  /* clocks and reset */
  reg        clk;     // system clock
  reg        mem_clk; // clock for memory controller and dram
  reg        dot_clk; // video dot clock
  reg   [7:0]rst_ff;
  wire       rst;
  /* mpeg2 stream input */ 
  reg   [7:0]stream_data;
  reg        stream_valid;
  /* status output */ 
  wire       busy;
  wire       error;
  wire       interrupt;
  /* video output */
  wire       pixel_en;
  wire       h_sync;
  wire       v_sync;
  wire  [7:0]r; // red
  wire  [7:0]g; // green
  wire  [7:0]b; // blue
  wire  [7:0]y; // luminance
  wire  [7:0]u; // chrominance
  wire  [7:0]v; // chrominance
  /* register file interface */
  reg   [3:0]reg_addr;
  reg        reg_wr_en;
  reg  [31:0]reg_dta_in;
  reg        reg_rd_en;
  wire [31:0]reg_dta_out;
  /* memory controller interface */
  wire  [1:0]mem_req_rd_cmd;
  wire [21:0]mem_req_rd_addr;
  wire [63:0]mem_req_rd_dta;
  wire       mem_req_rd_en;
  wire       mem_req_rd_valid;
  wire [63:0]mem_res_wr_dta;
  wire       mem_res_wr_en;
  wire       mem_res_wr_almost_full;
  wire [33:0]testpoint;
 
  /*
   * clocks 
   */
 
  initial
    begin
      clk = 1'b0;
      #(`CLK_PERIOD/2);
      forever #(`CLK_PERIOD/2) clk = ~clk;
    end
 
  initial
    begin
      mem_clk = 1'b0;
      #(`MEMCLK_PERIOD/2);
      forever #(`MEMCLK_PERIOD/2) mem_clk = ~mem_clk;
    end
 
  initial
    begin
      dot_clk = 1'b0;
      #(`VIDCLK_PERIOD/2);
      forever #(`VIDCLK_PERIOD/2) dot_clk = ~dot_clk;
    end
 
  /*
   * read mpeg2 clip from file "stream.dat"
   */
 
  integer    i;
  reg   [7:0]stream[0:`MAX_STREAM_LENGTH];
 
  initial #0
    begin
      $readmemh("stream.dat", stream, 0, `MAX_STREAM_LENGTH);
      rst_ff    = 8'b0;
      i         = 0;
      stream_data  = 0;
      stream_valid = 0;
      reg_dta_in = 32'd0;
      reg_addr  = 4'b0;
      reg_wr_en = 0;
      reg_rd_en = 0;
    end
 
  assign rst = rst_ff[7];
 
  always @(posedge clk)
    rst_ff <= {rst_ff[6:0], 1'b1};
 
  /* timing simulation: add #1 = 1 ns hold time to stream_data and stream_valid */
 
  always @(posedge clk)
    if (~rst)
      begin
        i <= 0;
        stream_data <= #1 0;
        stream_valid <= #1 1'b0;
      end
    else if (~busy && (i < `MAX_STREAM_LENGTH) && (^stream [i] !== 1'bx))
      begin
        i <= i + 1;
        stream_data <= #1 stream [i];
        stream_valid <= #1 1'b1;
      end
    else
      begin
        i <= i;
        stream_data <= #1 0;
        stream_valid <= #1 1'b0;
      end
 
   /*
    * mpeg2 decoder
    */
 
  mpeg2video mpeg2 (
    .clk(clk), 
    .mem_clk(mem_clk), 
    .dot_clk(dot_clk), 
    .rst(rst), 
    .stream_data(stream_data), 
    .stream_valid(stream_valid), 
    .reg_addr(reg_addr), 
    .reg_wr_en(reg_wr_en), 
    .reg_dta_in(reg_dta_in), 
    .reg_rd_en(reg_rd_en), 
    .reg_dta_out(reg_dta_out), 
    .busy(busy), 
    .error(error), 
    .interrupt(interrupt), 
    .watchdog_rst(),
    .r(r), 
    .g(g), 
    .b(b), 
    .y(y), 
    .u(u), 
    .v(v), 
    .pixel_en(pixel_en), 
    .h_sync(h_sync), 
    .v_sync(v_sync), 
    .c_sync(), 
    .mem_req_rd_cmd(mem_req_rd_cmd), 
    .mem_req_rd_addr(mem_req_rd_addr), 
    .mem_req_rd_dta(mem_req_rd_dta), 
    .mem_req_rd_en(mem_req_rd_en), 
    .mem_req_rd_valid(mem_req_rd_valid), 
    .mem_res_wr_dta(mem_res_wr_dta), 
    .mem_res_wr_en(mem_res_wr_en), 
    .mem_res_wr_almost_full(mem_res_wr_almost_full),
    .testpoint(testpoint),
    .testpoint_dip(4'h0),
    .testpoint_dip_en(1'b1)
    );
 
   /*
    * Memory controller
    */
 
    mem_ctl mem_ctl (
    .clk(mem_clk),
    .rst(rst),
    .mem_req_rd_cmd(mem_req_rd_cmd),
    .mem_req_rd_addr(mem_req_rd_addr),
    .mem_req_rd_dta(mem_req_rd_dta),
    .mem_req_rd_en(mem_req_rd_en),
    .mem_req_rd_valid(mem_req_rd_valid),
    .mem_res_wr_dta(mem_res_wr_dta),
    .mem_res_wr_en(mem_res_wr_en),
    .mem_res_wr_almost_full(mem_res_wr_almost_full)
    );
 
`ifdef DEBUG_DUMP
  /*
   * begin vcd dump 
   */
 
  initial
    // generate vcd dump, for use with gtkwave 
    // set IVERILOG_DUMPER=lxt environment variable for lxt format (smaller)
    // export IVERILOG_DUMPER=lxt
    begin
      $dumpfile("testbench.lxt");
//      $dumpvars;
//        $dumpvars(0, testbench.mpeg2.resample.resample_dta);
//        $dumpvars(0, testbench.mpeg2.resample.resample_bilinear);
        $dumpvars(0, testbench.mpeg2.probe);
    end
`endif
 
`ifdef DUMP_TVOUT
 
/*
  Writes rgb output to portable pixmap graphics file "tv_out_xxxx.ppm".
 */
 
  integer fp = 0;
  reg [31:0]fname_cnt = "0000";
  integer v_sync_seen = 1;
  integer pixel_count = 0;
  integer img_count = 0;
 
  wire [11:0]syncgen_horizontal_resolution;
  wire [11:0]syncgen_horizontal_sync_start;
  wire [11:0]syncgen_horizontal_sync_end;
  wire [11:0]syncgen_horizontal_length;
  wire [11:0]dot_vertical_resolution;
  wire [11:0]dot_vertical_sync_start;
  wire [11:0]dot_vertical_sync_end;
  wire [11:0]dot_vertical_length;
  wire       dot_interlaced;
  wire [11:0]syncgen_horizontal_halfline;
 
  /*
   * Note: these assignments have to be modified if synthesis assigns other names to these nets. 
   * Use commands such as "find signals -r *name*" at the simulator prompt to find suitable candidates.
   */
 
  assign syncgen_horizontal_resolution = testbench.mpeg2.syncgen_intf.syncgen_horizontal_resolution;
  assign syncgen_horizontal_sync_start = testbench.mpeg2.syncgen_intf.syncgen_horizontal_sync_start;
  assign syncgen_horizontal_sync_end   = testbench.mpeg2.syncgen_intf.syncgen_horizontal_sync_end;
  assign syncgen_horizontal_length     = testbench.mpeg2.syncgen_intf.syncgen_horizontal_length;
  assign syncgen_horizontal_halfline   = testbench.mpeg2.syncgen_intf.syncgen_horizontal_halfline;
  assign dot_vertical_resolution       = testbench.mpeg2.syncgen_intf.dot_vertical_resolution;
  assign dot_vertical_sync_start       = testbench.mpeg2.syncgen_intf.dot_vertical_sync_start;
  assign dot_vertical_sync_end         = testbench.mpeg2.syncgen_intf.dot_vertical_sync_end;
  assign dot_vertical_length           = testbench.mpeg2.syncgen_intf.dot_vertical_length;
  assign dot_interlaced                = testbench.mpeg2.syncgen_intf.dot_interlaced;
 
  always @(posedge dot_clk)
    begin
      if (v_sync) v_sync_seen = 1;
 
      if (v_sync_seen && pixel_en && (^syncgen_horizontal_length !== 1'bx) && (^dot_vertical_length !== 1'bx))
        begin
          // pad and close old dump file
          if (fp != 0)
            begin
              while (pixel_count < (syncgen_horizontal_length + 1) * (dot_vertical_length + 1))
                begin
                  $fwrite(fp, " 48  48  48\n");
                  pixel_count = pixel_count + 1;
                end
              $fclose(fp);
            end
          v_sync_seen = 0;
          pixel_count = 0;
          // open new dump file
          fp=$fopen({"tv_out_", fname_cnt, ".ppm"}, "w");
          /* implement a counter for string "fname_cnt" */
          if (fname_cnt[7:0] != "9")
            fname_cnt[7:0] = fname_cnt[7:0] + 1;
          else
            begin
              fname_cnt[7:0] = "0";
              if (fname_cnt[15:8] != "9")
                fname_cnt[15:8] = fname_cnt[15:8] + 1;
              else
                begin
                  fname_cnt[15:8] = "0";
                  if (fname_cnt[23:16] != "9")
                    fname_cnt[23:16] = fname_cnt[23:16] + 1;
                  else
                    begin
                      fname_cnt[23:16] = "0";
                      if (fname_cnt[31:24] != "9")
                        fname_cnt[31:24] = fname_cnt[31:24] + 1;
                      else
                        fname_cnt[31:24] = "0";
                    end
                end
            end
          // write header
          if (fp != 0) 
            begin
              $fwrite(fp, "P3\n"); // Portable pixmap, ascii.
              $timeformat(-3, 2, " ms", 8);
              $fwrite(fp, "# picture %0d  @ %t\n", img_count, $time);
              $timeformat(-9, 2, " ns", 20);
              $fwrite(fp, "# horizontal resolution %0d sync_start %0d sync_end %0d length %0d\n", syncgen_horizontal_resolution, syncgen_horizontal_sync_start, syncgen_horizontal_sync_end, syncgen_horizontal_length);
              $fwrite(fp, "# vertical resolution %0d sync_start %0d sync_end %0d length %0d\n", dot_vertical_resolution, dot_vertical_sync_start, dot_vertical_sync_end, dot_vertical_length);
              $fwrite(fp, "# interlaced %0d halfline %0d\n", dot_interlaced, syncgen_horizontal_halfline);
              img_count = img_count + 1;
              $fwrite(fp, "%5d %5d 255\n", syncgen_horizontal_length + 1, dot_vertical_length + 1);
            end
        end
 
      // write rgb values to dump file
      if (fp != 0) 
        begin
          if (pixel_en && ((^r === 1'bx) || (^g === 1'bx) || (^g === 1'bx))) 
            begin
              $fwrite(fp, "    255   0   0\n"); // draw pixel in vivid red if r, g or b undefined
            end
          else if (pixel_en) $fwrite(fp, "%3d %3d %3d\n", r, g, b);
          else if (v_sync || h_sync) $fwrite(fp, "  0   0   0\n");
          else $fwrite(fp, " 48  48  48\n");
          pixel_count = pixel_count + 1;
        end
    end
 
`endif
 
`ifdef DEBUG
  always @(posedge clk)
    if (error) 
      begin
        $display("%m\terror asserted\n");
//        $stop;
      end
 
  always @(posedge clk) 
    $strobe("%m\tcnt: %h stream_data: 8'h%h stream_valid: %d rst: %d busy: %d interrupt: %d reg_dta_out: %h", i, stream_data, stream_valid, rst, busy, interrupt, reg_dta_out);
`endif
 
endmodule
/* not truncated */
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

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