Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
10 years ago

Simulation Problem about a D filp flop by modelsim ALTERA 10.1d

Why reg and wire have different behaviors in RTL simulation?

The module is pasted below.


module FIFO# (parameter WIDTH = 8, DEPTH = 16)
    (
    input  DataIn,
    input RdReq,
    input WtReq,
    input Clk,
    input Reset,
    output reg  DataOut,
    output reg Full,
    output reg Empty);
    reg  writep;
    reg  readp;
    reg  memory;
    reg  tempwp;
    reg  temprp;
    
    reg almostfull;
    reg almostempty;
    
    reg rdreqbuffer;
    reg rd;
    reg wtreqbuffer;
    reg wtreqbuffer3;
    reg wt;
    
    integer fifo_i;
    
    always@(*) rd = (~rdreqbuffer) & RdReq;
    always@(*) wt = (~wtreqbuffer) & WtReq;
    
    always@(posedge Clk or negedge Reset)
    begin
        if(Reset == 0)
            rdreqbuffer <= 1;
        else
            rdreqbuffer <= RdReq;
    end
    
    always@(WtReq) wtreqbuffer3 = WtReq;
    
    always@(posedge Clk or negedge Reset)
    begin
        if(Reset == 0)
            wtreqbuffer <= 1;
        else
            wtreqbuffer <= wtreqbuffer3;
    end
    
    
    always@(writep)
        tempwp = writep + 1'b1;
    
    always@(readp)
        temprp = readp + 1'b1;
    
    always@(tempwp,temprp,writep,readp)
    begin
        almostfull = (tempwp == readp)?1'b1:1'b0;
        almostempty = (temprp == writep)?1'b1:1'b0;
    end
    
    always@(posedge Clk or negedge Reset)
    begin
        if(Reset == 0)
            for(fifo_i = 0; fifo_i < DEPTH; fifo_i = fifo_i + 1)
            begin
                memory <= 0;
            end
        else if(wt == 1 && Full == 0)
            for(fifo_i = 0; fifo_i < DEPTH; fifo_i = fifo_i + 1)
            begin
                memory <= (writep == fifo_i)?DataIn:memory;
            end
        else
            for(fifo_i = 0; fifo_i < DEPTH; fifo_i = fifo_i + 1)
            begin
                memory <= memory;
            end
    end
    
    always@(posedge Clk or negedge Reset)
    begin
        if(Reset == 0)
            DataOut <= 0;
        else if(rd == 1 && Empty == 0)
            DataOut <= memory;
        else
            DataOut <= DataOut;
    end
    
    always@(posedge Clk or negedge Reset)
    begin
        if(Reset == 0)
            writep <= 0;
        else if(wt == 1 && Full == 0)
            writep <= writep + 1'b1;
        else
            writep <= writep;
    end
    
    always@(posedge Clk or negedge Reset)
    begin
        if(Reset == 0)
            readp <= 0;
        else if(rd == 1 && Empty == 0)
            readp <= readp + 1'b1;
        else
            readp <= readp;
    end
    
    always@(posedge Clk or negedge Reset)
    begin
        if(Reset == 0)
            Empty <= 1;
        else if((almostempty == 1 && rd == 1 && wt == 0) || (Empty == 1 && wt == 0))
           Empty <= 1;
        else
            Empty <= 0;            
    end
    
    always@(posedge Clk or negedge Reset)
    begin
        if(Reset == 0)
            Full <= 0;
        else if((almostfull == 1 && wt == 1 && rd == 0) || (Full == 1 && rd ==0))
           Full <= 1;
        else
            Full <= 0;            
    end
    function integer widthOf;
        input    integer num;
        if(num == 0) 
            widthOf = 1;
        else 
            for(widthOf = 0; num != 0; widthOf = widthOf + 1) num = num>>1;
    endfunction
endmodule

And the testbanch is as follows.


`timescale 10ps/1ps
module FIFO_tb  ; 
parameter WIDTH  = 8 ;
parameter DEPTH  = 16 ; 
  reg    DataIn   ; 
  wire    DataOut   ; 
  reg    Clk; 
  reg    RdReq   ; 
  wire   Empty   ; 
  wire   Full   ; 
  reg    Reset   ; 
  reg    WtReq   ; 
  FIFO   # ( WIDTH , DEPTH)
   DUT  ( 
       .DataIn (DataIn ) ,
      .DataOut (DataOut ) ,
      .Clk (Clk ) ,
      .RdReq (RdReq ) ,
      .Empty (Empty ) ,
      .Full (Full ) ,
      .Reset (Reset ) ,
      .WtReq (WtReq ) ); 
  initial 
  begin 
  Clk <= 1'b1;
  forever# 10  Clk <= !Clk;
  end
  
  integer i,j;
  
  initial
  begin
 # 80
  for ( i = 1 ; i < 9; i = i + 1) 
  begin
   # 20 DataIn <= i;
  end  
  end
  
  initial
  begin
  WtReq <= 0;  
 # 100 WtReq <= 1;
 # 160  WtReq <= 0; 
  end
  
  initial
  begin
  RdReq <= 0;  
 # 12 //RdReq = 1;
  for ( j = 1 ; j < 18; j = j + 1) 
  begin
   # 20 RdReq <= j%2;
  end 
  end
  
  initial
  begin
  Reset <= 0;
 # 5  Reset <= 1;
  end
endmodule

What puzzles me is claiming the wt is reg or wire(always@(*) wt = XXXX or assign wt = XXXX) is quite different!

Claiming as wire type the modelsim will fetch 1 at which time Wtreq and Clk rise or fall at the same time, but claiming as reg type will make it behave more like a D flip flop.

4 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    No desciption in this thread?

    --- Quote End ---

    I just find this problem when I do RTL simulation with upper code. It's easy to find the same problem use the following code.

    
    module test(
    	input Clock,
    	input Reset,
    	input Signal,
    	output SignalPosEdge
    );
    //reg signal;
    //always@(*) signal = Signal;
    reg signalbuffer1;
    clkctrl gclk(
    	.inclk(Clock),
    	.outclk(gclock)
    );
    always@(posedge gclock or negedge Reset)
    begin
    	if(Reset == 0)
    		signalbuffer1 <= 0;
    	else
    		signalbuffer1 <= Signal;
    //              signalbuffer1 <= signal;
    end
    assign SignalPosEdge = (~signalbuffer1)&Signal;
    endmodule
    

    
    `timescale 1ns/100ps
    module test_tb  ; 
     
      reg    Clock   ; 
      wire    SignalPosEdge   ; 
      reg    Signal   ; 
      reg    Reset   ; 
      test  
       DUT  ( 
           .Clock (Clock ) ,
          .SignalPosEdge (SignalPosEdge ) ,
          .Signal (Signal ) ,
          .Reset (Reset ) ); 
    initial 
    begin
      Clock  = 1;
      forever# 10 Clock = ~Clock;
    end
    initial
    begin
      Reset = 0;
     # 40 Reset = 1;  
    end 
    initial
    begin
      Signal = 0;
     # 40 Signal = 1;  
    end 
    endmodule
    

    In the module, test, I want to synchronize Signal's posedge to a cycle of Clock. So I user a D filp-flop to buffer Signal, and use "SignalPosEdge = (~signalbuffer1)&Signal" to get the synchronized pulse. But if using my testbanch, you will only find SignalPosEdge have a risk issue at# 40, being 1 and getting down immediately. While I hope there is one cycle Clock pulse to indicate the posedge of Signal. And if you use the comment sentences in the module, test and the same testbanch, you will find that RTL simulation result is quite different. There is a cycle long pulse in SignalPosEdge.

    Thank you for your reading. Please forgive my poor English.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    There is no difference between doing:

    wire out;
    assign out = in1 ^ in2;
    and
    reg out;
    always @ (*)
        out = in1 ^ in2;

    If you put either into a device you will get the same result. If you simulate these you will also see the same result.

    However, what you are doing is a little different and you need to understand the way in which ModelSim (or any other simulator) works. When you generate stimulus that occurs at the same point in time (in your case @ 40ns both 'clock' & 'Signal' change) the simulator needs to decide how to evaluate the new state of each signal. Whereas your hardware (your FPGA) does this simultaneously (in parallel, albeit with propagation delays), the simulator does this sequentially over a number of simulation cycles. These cycles aren't 1ns, or 1ps. They don't have any time associated with them they are simply passes of the code. ModelSim will then display this as having occurred simultaneously. This is why you often see glitches that have no time duration associated with them. This is where ModelSim has evaluated a signal in one state (e.g. your 'SignalPosEdge' signal is evaluated HIGH) but on the next simulation cycle to simulator determines it actually needs to be in the other state ('SignalPosEdge' is re-assessed LOW). So, ModelSim displays that as what appears to be a glitch.

    So, I suggest you change the point at which events occur in your simulation. Change "#40 Signal = 1;" to "#35 Signal = 1;" or "#45 Signal = 1;". You will give the simulator an easier job of analysing your puzzle and, I think you'll learn a little more about your code and ModelSim. If you don't think that appropriately represents your real system then you will need to rethink how your code and how to stimulate your simulation.

    Cheers,

    Alex

    PS. Sorry if this is a little difficult to understand but you are asking about something a little complex... :eek:
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    There is no difference between doing:
    wire out;
    assign out = in1 ^ in2;
    and
    reg out;
    always @ (*)
        out = in1 ^ in2;

    If you put either into a device you will get the same result. If you simulate these you will also see the same result.

    However, what you are doing is a little different and you need to understand the way in which ModelSim (or any other simulator) works. When you generate stimulus that occurs at the same point in time (in your case @ 40ns both 'clock' & 'Signal' change) the simulator needs to decide how to evaluate the new state of each signal. Whereas your hardware (your FPGA) does this simultaneously (in parallel, albeit with propagation delays), the simulator does this sequentially over a number of simulation cycles. These cycles aren't 1ns, or 1ps. They don't have any time associated with them they are simply passes of the code. ModelSim will then display this as having occurred simultaneously. This is why you often see glitches that have no time duration associated with them. This is where ModelSim has evaluated a signal in one state (e.g. your 'SignalPosEdge' signal is evaluated HIGH) but on the next simulation cycle to simulator determines it actually needs to be in the other state ('SignalPosEdge' is re-assessed LOW). So, ModelSim displays that as what appears to be a glitch.

    So, I suggest you change the point at which events occur in your simulation. Change "#40 Signal = 1;" to "#35 Signal = 1;" or "#45 Signal = 1;". You will give the simulator an easier job of analysing your puzzle and, I think you'll learn a little more about your code and ModelSim. If you don't think that appropriately represents your real system then you will need to rethink how your code and how to stimulate your simulation.

    Cheers,

    Alex

    PS. Sorry if this is a little difficult to understand but you are asking about something a little complex... :eek:

    --- Quote End ---

    Thank you anyway!

    I'm really agreed with you. There is no difference between the two xxxx.vo files and in gate-level simulation.

    Even a D flip flop have setup and hold time for input signal corresponding to clock edge . Furthermore, ModelSim simulate the wave in a special compiled sequence. So, in a word, not using that clock edge, I should change the signal after it to make the RTL simulation right, vise-versa. Did I comprehend it right?

    Regards,

    Hubert

    PS. You explained it in a quite understandable way with simple language.