Author Topic: Verilog Simulation Testbench timing output async events.  (Read 900 times)

0 Members and 1 Guest are viewing this topic.

Offline BrianHGTopic starter

  • Super Contributor
  • ***
  • Posts: 7726
  • Country: ca
Verilog Simulation Testbench timing output async events.
« on: October 07, 2021, 07:36:28 am »
Ok, say I have a simulation where I want a few manual 10 MHz clock cycles, I could write:

Code: [Select]
task run ();
begin
  clk = 1 ;
  #(50);
  clk = 0 ;
  out1 = 1;
  out2 = 1;
  out3 = 1;
  #(50);
  clk = 1 ;
  #(50);
  clk = 0 ;
  out1 = 0;
  out2 = 0;
  out3 = 0;
  #(50);
end
endtask

Now, say I want to place a few stimulations at specific times inside that cycle, I want the first out1/2/3=1 to be delayed by an additional adjustable parameters, however, I do not want any other timing to change:


Code: [Select]
task run ();
begin
  clk = 1 ;
  #(50);
  clk = 0 ;
  #(oldy_1) out1 = 1;
  #(odly_2) out2 = 1;
  #(odly_3) out3 = 1;
  #(50);
  clk = 1 ;
  #(50);
  clk = 0 ;
  out1 = 0;
  out2 = 0;
  out3 = 0;
  #(50);
end
endtask

The problem with the above code is that the #(oldy_1/2/3) will mess up the clock timing and each one affects the timing of the next, especially if I need odly_2 to be shorter than odly_1.

Instead of doing all the math, is there an easy way to specify the #(oldy_1/2/3) as a one-time event to take place at that time after the previous normal #(50), but not mess up the normal #(50) delay events?
 

Offline dtodorov

  • Contributor
  • Posts: 46
  • Country: bg
Re: Verilog Simulation Testbench timing output async events.
« Reply #1 on: October 07, 2021, 11:01:38 am »
fork
...
join?
 

Offline BrianHGTopic starter

  • Super Contributor
  • ***
  • Posts: 7726
  • Country: ca
Re: Verilog Simulation Testbench timing output async events.
« Reply #2 on: October 07, 2021, 02:23:50 pm »
Thanks dtodorov, but I ended up making a separate :

Code: [Select]
always #(100) begin

if (($time/100)==(etc[ 6]/100)) lZ80_DATA       = 8'bzzzzzzzz ;
if (($time/100)==(etc[53]/100)) lZ80_DATA       = nZ80_DATA ;
if (($time/100)==(etc[42]/100)) lZ80_ADDR       = nZ80_ADDR ;

if (($time/100)==(etc[ 8]/100)) lZ80_MREQ       = 0 ;
if (($time/100)==(etc[12]/100)) lZ80_MREQ       = 1 ;
if (($time/100)==(etc[30]/100)) lZ80_WR         = 0 ;
if (($time/100)==(etc[32]/100)) lZ80_WR         = 1 ;
if (($time/100)==(etc[13]/100)) lZ80_RD         = 0 ;
if (($time/100)==(etc[23]/100)) lZ80_RD         = 1 ;

if (($time/100)==(etc[17]/100)) lZ80_wait_sh    = 1 ;
if (($time/100)==(etc[18]/100)) lZ80_wait_sh    = 0 ;

if (($time/100)==(etc[25]/100)) lZ80_read_sh    = 1 ;
if (($time/100)==(etc[16]/100)) lZ80_read_sh    = 0 ;

end

And above in my task code, I have:

Code: [Select]
// Timings found in Zilog Z8400/Z84C00 NMOS/CMOS Z80 CPU Product Specification data sheet.
//                                      4 MHz,  6 MHz,  8 MHz, 10 MHz, 20 MHz
localparam  int  tc6        [0:4] = '{ 110000,  90000,  80000,  65000,  57000}; // TdCr(A)
localparam  int  tc8        [0:4] = '{  85000,  70000,  60000,  55000,  40000}; // TdCf(MREQf)
localparam  int  tc12       [0:4] = '{  85000,  70000,  60000,  55000,  40000}; // TdCf(MREQr)
localparam  int  tc13       [0:4] = '{  95000,  80000,  70000,  65000,  40000}; // TdCf(RDf)
localparam  int  tc23       [0:4] = '{  85000,  70000,  60000,  55000,  40000}; // TdCf(RDr)
localparam  int  tc30       [0:4] = '{  80000,  70000,  60000,  55000,  40000}; // TdCf(WRf)
localparam  int  tc32       [0:4] = '{  80000,  70000,  60000,  55000,  40000}; // TdCf(WRr)
localparam  int  tc42       [0:4] = '{  90000,  80000,  70000,  65000,  40000}; // TdCr(Dz)
localparam  int  tc53       [0:4] = '{ 150000, 130000, 115000, 110000,  75000}; // TdCf(D)

.....
                                          @(posedge Z80_CLK);
                                          Z80_CKS_pos   =  1 ;

                                          lZ80_ADDR     =  16'bxxxxxxxxxxxxxxxx;

                                          nZ80_ADDR     =  tx_addr;
                                          nZ80_DATA     =  tx_data ;

                                          etc[6]        =  tc6[zsg]  + $time ;                          // Time until the Z80_data bus goes HI-Z
                                          etc[42]       =  tc42[zsg] + $time ;                          // Time until the Z80_data bus address is valid.
                                          etc[8]        =  tc8 [zsg] + $time + zp ;                     // Time until the Z80_MREQ goes low.

                                          etc[53]       =  tc53[zsg] + $time + zp ;                     // Time until the Z80 output data is valid.  +zp means wait for the falling clock

                                          @(posedge Z80_CLK);
                                          Z80_CKS_pos   =  2 ;

                                          etc[17]       =  $time + zp - tc17[zsg] - (FPGA_IO_tsu*1000) ; // Setup time for sampling the 'WAIT' input.
                                          etc[18]       =  tc18[zsg] + $time + zp - (FPGA_IO_tsu*1000) ; // Hold  time for sampling the 'WAIT' input.
                                         
                                          etc[30]       =  tc30[zsg] + $time + zp ;                      // Time until the Z80_WR goes low.


                                          @(posedge Z80_CLK);
                                          Z80_CKS_pos   =  3 ;

                                          etc[12]       =  tc12[zsg] + $time + zp ;                      // Time until the Z80_MREQ goes high.
                                          etc[32]       =  tc32[zsg] + $time + zp ;                      // Time until the Z80_WR   goes high.
                                          etc[23]       =  tc23[zsg] + $time + zp ;                      // Time until the Z80_RD   goes high.

                                          @(negedge Z80_CLK); // Z80_CKS_pos   =  5 ;

This appears to work fine.
It generates a Z80 write bus cycle according to the data-sheet's worst case scenario for a selected MHz model.

 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf