Intel® Quartus® Prime Software
Intel® Quartus® Prime Design Software, Design Entry, Synthesis, Simulation, Verification, Timing Analysis, System Design (Platform Designer, formerly Qsys)
17255 Discussions

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

Altera_Forum
Honored Contributor II
2,219 Views

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.
0 Kudos
4 Replies
Altera_Forum
Honored Contributor II
1,385 Views

No desciption in this thread?

0 Kudos
Altera_Forum
Honored Contributor II
1,385 Views

 

--- 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.
0 Kudos
Altera_Forum
Honored Contributor II
1,385 Views

There is no difference between doing:wire out; assign out = in1 ^ in2;andreg 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:
0 Kudos
Altera_Forum
Honored Contributor II
1,385 Views

 

--- Quote Start ---  

There is no difference between doing:wire out; assign out = in1 ^ in2;andreg 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.
0 Kudos
Reply