Author Topic: Confusing myself with a very simple verilog testbench  (Read 1772 times)

0 Members and 1 Guest are viewing this topic.

Offline jeremyTopic starter

  • Super Contributor
  • ***
  • Posts: 1079
  • Country: au
Confusing myself with a very simple verilog testbench
« on: June 06, 2016, 12:29:33 pm »
Hi all,

Not sure if this is the right place to ask this, but I am really confusing myself and could use some help   :(

I'm trying to write a verilog testbench. It's basically supposed to be a waveform that represents an AXI stream transaction:

Code: [Select]
module master_stream_handshake();
    reg axis_aresetn;
    reg axis_aclk;
    reg [7:0] axis_tdata;
    reg axis_tready;
    reg axis_tvalid;

    initial begin
        $dumpfile("stream.vcd");
        $dumpvars;

        axis_aclk = 0;
        axis_aresetn = 0;

        axis_tdata = 0;
        axis_tvalid = 0;
        axis_tready = 0;

        #3 axis_aresetn = 1;

        #4 axis_tvalid = 1;
           axis_tready = 1; // set by slave

        #2 axis_tdata = 5;
        #2 axis_tdata = 6;
        #2 axis_tdata = 7;
        #2 axis_tdata = 8;
        #2 axis_tdata = 9;

        #2 axis_tready = 0;

        #10 $finish();
    end

    always begin
        #1 axis_aclk = axis_aclk ^ 1;
    end

endmodule

I'm simulating it in iverilog and viewing it with GTKWave (clock period is 2 seconds):


The thing I am getting really confused with is the timing of "writes" (for lack of better word). Basically, my question boils down to this: if I had a bunch of ideal rising edge triggered flip-flops connected to "axis_tdata", what would be its state just after the marker (let's say, 9.1 seconds)? Would it be storing the old value (0x00) or would it be storing 0x05?

I thought that in verilog all "reads" of signals were performed before any "writes", so I would have thought that the register would have 0x00 clocked in at the cursor, then 0x05 would be at the next rising edge. However, GTKWave says the value is 0x05  :-[

Looking at the specification itself makes a lot more sense, because all of the waves aren't locked to the clock edges:

Can anyone please point me in the right direction?
 

Offline 6thimage

  • Regular Contributor
  • *
  • Posts: 181
  • Country: gb
Re: Confusing myself with a very simple verilog testbench
« Reply #1 on: June 06, 2016, 01:58:37 pm »
The thing I am getting really confused with is the timing of "writes" (for lack of better word). Basically, my question boils down to this: if I had a bunch of ideal rising edge triggered flip-flops connected to "axis_tdata", what would be its state just after the marker (let's say, 9.1 seconds)? Would it be storing the old value (0x00) or would it be storing 0x05?

That really depends - if you are doing behaviourally simulation it will be 0x05, if you are dealing with a real device (post place simulation) it will likely violate timing.

I thought that in verilog all "reads" of signals were performed before any "writes", so I would have thought that the register would have 0x00 clocked in at the cursor, then 0x05 would be at the next rising edge. However, GTKWave says the value is 0x05  :-[

Yes, normally reads happen on rising edges of clocks with writes being on the falling edge. But you're simulation isn't clocked - you are setting arbitrary values to signals. If you want the read on rising, write on falling you need to use an 'always @(posedge clk)' where clk is your clock signal, otherwise you have to ensure that the correct clock edges are used.

The best way to simulate this is to either write a module that outputs the data - i.e. something that will work in hardware - or to write yourself a task. If you write it as a task, use a lot of '@(posedge sig)' where sig is the signal you want to align to (i.e. a clock or module output signal).
 

Offline kfnight

  • Regular Contributor
  • *
  • Posts: 71
Re: Confusing myself with a very simple verilog testbench
« Reply #2 on: June 06, 2016, 06:10:37 pm »
In Verilog RTL, if the design's ports change value at the positive edge of the clock, then you can unambiguously drive and sample the ports in your testbench at the negative edge of the clock. So rather than

Code: [Select]
#3 axis_aresetn = 1;
use

Code: [Select]
@(negedge axis_aclk); axis_aresetn = 1;
If you want to wait multiple clock cycles, you can use the repeat loop.

Code: [Select]
repeat (5) @(negedge axis_aclk);
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf