Thanks dtodorov, but I ended up making a separate :
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:
// 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.