Subversion Repositories ngs

Rev

Rev 153 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed | ?url?

  1. // testbench for chan_ctrl.v
  2.  
  3. `timescale 10ns/1ns
  4.  
  5. `define HALF_CLK (5.0)
  6.  
  7.  
  8. class channel_data;
  9.  
  10.         bit [13:0] base;
  11.  
  12.         bit [19:0] size;
  13.         bit [19:0] loop; // actually loop-size
  14.  
  15.         bit [ 5:0] add_int;
  16.         bit [11:0] add_frac;
  17.  
  18.         bit [19:0] offset_int;
  19.         bit [11:0] offset_frac;
  20.  
  21.         bit        surround;
  22.         bit        loopena;
  23.  
  24.         bit [ 5:0] vol_left;
  25.         bit [ 5:0] vol_right;
  26.  
  27.  
  28.  
  29.         function void init();
  30.  
  31.                 base = $random()>>(32-14);
  32.  
  33.                 add_int = $random()>>(32-6);
  34.                 add_frac = $random()>>(32-12);
  35.  
  36.                 offset_int = $random()>>(32-20);
  37.                 offset_frac = $random()>>(32-12);
  38.  
  39.                 size = $random()>>(32-10); // TODO: greater sizes
  40.                 loop = {20{1'b1}};
  41.                 while(loop>=size)
  42.                         loop = $random()>>(32-10); // TODO: greater sizes
  43.  
  44.                 surround = $random()>>(32-1);
  45.                 loopena  = $random()>>(32-1);
  46.  
  47.                 vol_left  = $random()>>(32-6);
  48.                 vol_right = $random()>>(32-6);
  49.         endfunction
  50.  
  51.  
  52.         function void update();
  53.  
  54.                 bit cy;
  55.  
  56.                 int new_off;
  57.  
  58.                 bit [21:0] addr;
  59.  
  60.  
  61.                 {cy,offset_frac} = {1'b0, offset_frac} + {1'b0, add_frac};
  62.  
  63.                 new_off = {31'd0, cy} + {26'd0,add_int} + {12'd0,offset_int};
  64.  
  65.                 if( new_off >= size )
  66.                 begin
  67.                         new_off = new_off - size + loop;
  68.                 end
  69.                
  70.                 offset_int = new_off[19:0];
  71.         endfunction
  72.  
  73.  
  74.  
  75.  
  76.  
  77.  
  78.         function int get_word(input int wnum);
  79.                 // return words suitable for channels state
  80.                 if( wnum==0 )
  81.                         get_word = {offset_int,offset_frac};
  82.                 else if( wnum==1 )
  83.                         get_word = {add_int, add_frac, loopena, surround, vol_left, vol_right};
  84.                 else if( wnum==2 )
  85.                         get_word = { (4'd0|$random()), size, base[7:0] };
  86.                 else if( wnum==3 )
  87.                         get_word = { (4'd0|$random()), loop-size, 2'b0, base[13:8] };
  88.                 else
  89.                         $stop;
  90.         endfunction
  91.  
  92.  
  93.         function bit [21:0] get_addr();
  94.  
  95.                 get_addr = base*256 + offset_int;
  96.         endfunction
  97.  
  98.  
  99.         function bit [6:0] get_vol_left();
  100.                 get_vol_left = {1'b0, vol_left};
  101.         endfunction
  102.  
  103.  
  104.         function bit [6:0] get_vol_right();
  105.                 if( surround )
  106.                         get_vol_right = 7'h7F - {1'b0, vol_right};
  107.                 else
  108.                         get_vol_right = {1'b0, vol_right};
  109.         endfunction
  110.  
  111.  
  112.         function bit [7:0] get_frac();
  113.                 get_frac = offset_frac[11:4];
  114.         endfunction
  115. endclass
  116.  
  117.  
  118.  
  119.  
  120.  
  121. module tb;
  122.  
  123.         reg clk;
  124.         reg rst_n;
  125.  
  126.  
  127.  
  128.         // sync counter
  129.         integer sync_cnt;
  130.         bit pre_sync;
  131.  
  132.         // DUT connections
  133.         wire [ 6:0] rd_addr;
  134.         tri0 [31:0] rd_data;
  135.  
  136.         wire [ 6:0] wr_addr;
  137.         wire [31:0] wr_data;
  138.         wire        wr_stb;
  139.  
  140.         reg         sync_stb;
  141.  
  142.         reg  [31:0] ch_enas;
  143.  
  144.         wire [ 7:0] out_data;
  145.         wire        out_stb_addr;
  146.         wire        out_stb_mix;
  147.  
  148.  
  149.         // channels memory
  150.         reg [31:0] channels_mem [0:127];
  151.  
  152.  
  153.  
  154.  
  155.  
  156.         // test data
  157.         channel_data chans[0:31];
  158.  
  159.         // generation fifos
  160.         reg [7:0] mix_fifo[$];
  161.         reg [7:0] addr_fifo[$];
  162.  
  163.  
  164.  
  165.  
  166.         // init tb data structures
  167.         initial
  168.         begin : chans_create
  169.  
  170.                 int i;
  171.                 for(i=0;i<32;i++) chans[i] = new;
  172.  
  173.                 mix_fifo.delete();
  174.                 addr_fifo.delete();
  175.         end
  176.  
  177.         // clock and reset gen
  178.         initial
  179.         begin
  180.                 rst_n = 1'b0;
  181.                 clk = 1'b1;
  182.                 forever #(`HALF_CLK) clk = ~clk;
  183.         end
  184.         //
  185.         initial
  186.         begin
  187.                 #(1);
  188.                 repeat (3) @(posedge clk);
  189.  
  190.                 rst_n <= 1'b1;
  191.         end
  192.  
  193.  
  194.         // sync generator
  195.         initial
  196.         begin
  197.                 sync_cnt = 0;
  198.                 pre_sync = 1'b0;
  199.                 sync_stb = 1'b0;
  200.         end
  201.         //
  202.         always @(posedge clk)
  203.         if( !rst_n )
  204.         begin
  205.                 sync_cnt <= 637;
  206.                 pre_sync <= 1'b0;
  207.                 sync_stb <= 1'b0;
  208.         end
  209.         else
  210.         begin
  211.                 if( sync_cnt<(640-1) )
  212.                         sync_cnt <= sync_cnt + 1;
  213.                 else
  214.                         sync_cnt <= 0;
  215.  
  216.                 pre_sync <= !sync_cnt;
  217.  
  218.                 sync_stb <= pre_sync;
  219.         end
  220.  
  221.  
  222.  
  223.  
  224.         // channels memory emulator
  225.         reg [31:0] rd_data_reg;
  226.         assign rd_data = rd_data_reg;
  227.         //
  228.         always @(posedge clk)
  229.                 rd_data_reg <= channels_mem[rd_addr];
  230.         //
  231.         always @(posedge clk)
  232.         if( wr_stb )
  233.                 channels_mem[wr_addr] <= wr_data;
  234.  
  235.  
  236.  
  237.         // fill queues off the output data
  238.         always @(posedge clk)
  239.         if( out_stb_mix ) mix_fifo.push_back(out_data);
  240.         //
  241.         always @(posedge clk)
  242.         if( out_stb_addr ) addr_fifo.push_back(out_data);
  243.  
  244.  
  245.  
  246.  
  247.         // channel generator/checker
  248.         always @(posedge clk)
  249.         if( sync_stb )
  250.         begin : chans
  251.                 int i;
  252.  
  253.                 // if there was previous iteration, check it
  254.  
  255.  
  256.  
  257.  
  258.                 // init channels for new iteration
  259.                 for(i=0;i<32;i++)
  260.                 begin
  261.                         chans[i].init();
  262.                        
  263.                         channels_mem[i*4+0] = chans[i].get_word(0);
  264.                         channels_mem[i*4+1] = chans[i].get_word(1);
  265.                         channels_mem[i*4+2] = chans[i].get_word(2);
  266.                         channels_mem[i*4+3] = chans[i].get_word(3);
  267.  
  268.                         chans[i].update();
  269.                 end
  270.         end
  271.  
  272.  
  273.  
  274.  
  275.  
  276.  
  277.  
  278.  
  279.  
  280.  
  281.         always @(posedge clk)
  282.                 ch_enas = 32'hFFFF_FFFF;
  283.  
  284.  
  285.  
  286.         // DUT
  287.         chan_ctrl chan_ctrl
  288.         (
  289.                 .clk  (clk  ),
  290.                 .rst_n(rst_n),
  291.  
  292.                 .rd_addr(rd_addr),
  293.                 .rd_data(rd_data),
  294.                                
  295.                 .wr_addr(wr_addr),
  296.                 .wr_data(wr_data),
  297.                 .wr_stb (wr_stb ),
  298.  
  299.                 .sync_stb(sync_stb),
  300.  
  301.                 .ch_enas(ch_enas),
  302.  
  303.                 .out_data    (out_data    ),
  304.                 .out_stb_addr(out_stb_addr),
  305.                 .out_stb_mix (out_stb_mix )
  306.         );
  307.  
  308.  
  309.  
  310.  
  311.  
  312. endmodule
  313.  
  314.