Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Why is the result of Post-Synthesis Simulation different from Behavioral Simulation?

Status
Not open for further replies.

manili

Member level 1
Member level 1
Joined
Sep 15, 2014
Messages
41
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,286
Activity points
1,603
Why the result of Post-Synthesis Simulation is deferent from Behavioral Simulation ?

Hi all,
The following code is an I-Cache of a processor. The behavioral simulation shows no problem at all and the Cache just works fine. But when I do Post-Synthesis-Simulation, it looks like that the Vivado-Synthesizer did a huge optimization which ruined the whole system! The problem is "dat_o" which is the result of caching is always false and it looks like the simulator is running the if-else statements in parallel which is very odd to me!

Here is the code :

Code:
`include "Global_Macros.v"

`define	i_cache_size			512

module I_Cache(
				rst_i,				//Global reset signal
				gbl_stl_i,			//Global stall signal
				rqst_i,				//Received a request from core
				extra_byte_cnt_i,	//Signal to tell the cache number of EXTRA bytes prefetch unit used in prev process
				adr_i,				//Starting address of requested datas
				ex_rdy_i,			//A signal to notify cache, the requested data from main memory is fetched by MMU
				ex_missed_dat_i,	//Missed data is transfered through this line to the cache
				ack_o,				//Acknowledge signal to notify the core that the data missing is ready
				dat_o,				//A line to transfer requested instructions from cache to the core
				ex_missed_adr_o		//A line to specify address of missed data for the MMU
);

	//Input signals :
	input	wire			rst_i;
	input	wire			gbl_stl_i;
	input	wire			rqst_i;
	input	wire	[1:0]	extra_byte_cnt_i;
	input	wire	[15:0]	adr_i;
	input	wire			ex_rdy_i;
	input	wire	[7:0]	ex_missed_dat_i;
	
	//Output signals :
	output	reg				ack_o;
	output	reg		[23:0]	dat_o;
	output	reg		[15:0]	ex_missed_adr_o;
	
	//Internal registers :
	reg		 		[9:0]	i;
	reg				[15:0]	cache				[0:`i_cache_size - 1];	//Valid[15]_Tag[14:8]_Data[7:0]
	
	//Assignments :
	
	//Blocks
	always @(rst_i or rqst_i or ex_rdy_i)
	begin
		if(rst_i)
		begin
			ack_o = 1'h0;
			dat_o = {3{`NOTHING}};
			ex_missed_adr_o = 16'h0;
			
			for(i = 0; i < `i_cache_size; i = i + 10'h1)
			begin
				cache[i][15] = 1'h0;
			end
		end
		else if(rqst_i)
		begin
			ack_o = 1'h0;
			
			if((extra_byte_cnt_i >= 2'h0) && (cache[adr_i[8:0] + 9'h0][15] != 1'h1 || cache[adr_i[8:0] + 9'h0][14:8] != adr_i[15:9]))
			begin
				//Request from main mem
				if(ex_rdy_i)
				begin
					cache[adr_i[8:0] + 9'h0] = {1'h1, adr_i[15:9], ex_missed_dat_i};
				end
				else
				begin
					ex_missed_adr_o = adr_i + 9'h0;
				end
			end
			else if((extra_byte_cnt_i >= 2'h1) && (cache[adr_i[8:0] + 9'h1][15] != 1'h1 || cache[adr_i[8:0] + 9'h1][14:8] != adr_i[15:9]))
			begin
				//Request from main mem
				if(ex_rdy_i)
				begin
					cache[adr_i[8:0] + 9'h1] = {1'h1, adr_i[15:9], ex_missed_dat_i};
				end
				else
				begin
					ex_missed_adr_o = adr_i + 9'h1;
				end
			end
			else if((extra_byte_cnt_i >= 2'h2) && (cache[adr_i[8:0] + 9'h2][15] != 1'h1 || cache[adr_i[8:0] + 9'h2][14:8] != adr_i[15:9]))
			begin
				//Request from main mem
				if(ex_rdy_i)
				begin
					cache[adr_i[8:0] + 9'h2] = {1'h1, adr_i[15:9], ex_missed_dat_i};
				end
				else
				begin
					ex_missed_adr_o = adr_i + 9'h2;
				end
			end
			else
			begin
				//Already cached, so return the result and turn off stall signal
				case(extra_byte_cnt_i)
					2'h0	:
					begin
						dat_o = {cache[adr_i[8:0] + 9'h0][7:0], dat_o[23:16], dat_o[15:8]};
					end
					2'h1	:
					begin
						dat_o = {cache[adr_i[8:0] + 9'h1][7:0], cache[adr_i[8:0] + 9'h0][7:0], dat_o[23:16]};
					end
					2'h2	:
					begin
						dat_o = {cache[adr_i[8:0] + 9'h2][7:0], cache[adr_i[8:0] + 9'h1][7:0], cache[adr_i[8:0] + 9'h0][7:0]};
					end
					default	:
					begin
						dat_o = dat_o;
					end
				endcase
				
				ack_o = 1'h1;
			end
		end
		else
		begin
			ack_o = 1'h0;
			dat_o = dat_o;
		end
	end
endmodule

This is the result of Behavioral-Simulation :

Behav_Sim.png

This is the result of Post-Synthesis-Simulation :

Post_Sim.png

Thank you.
 

Re: Why the result of Post-Synthesis Simulation is deferent from Behavioral Simulatio

It is because you missed a load of variables from the sensitivity list of your always block, because it is asynchronous logic.
You should be using always(*) for the block, as it will be updated also on adr_i, cache, ex_missed_dat_i.

I highly suggest though that you add a clocjk to the system and make the design synchronous.
 

Re: Why the result of Post-Synthesis Simulation is deferent from Behavioral Simulatio

TrickyDicky thanks for your reply.
I made the change as you suggested but as I predicted it made no changes at all :( .
Unfortunately due to some architectural problems I can't make the cache synchronous without huge changes.
Thank you very much.
 

Re: Why the result of Post-Synthesis Simulation is deferent from Behavioral Simulatio

I added a debugging signal to find out when the always block is being called.
Code:
always @(rst_i or rqst_i or ex_rdy_i)
begin
   if(rst_i)
   begin
      debug_signal = 1'h0;
   end
   ...
   debug_signal = ~debug_signal;
end
After synthesizing I realized that the simulator reached 10^6 times loop limit, so stoped. I want to know is it possible for the Vivado synthesizer to add debug_signal to the sensitivity list automatically ?
 

Re: Why the result of Post-Synthesis Simulation is deferent from Behavioral Simulatio

The always block is always called on the signals in the sensitivity list. You should have always @(*)
You should also use all non-blocking assignments rather than blocking..

But the use of logic without a clock is poor practice. You current code creates latches, which will cause you timing problems.
 

Re: Why the result of Post-Synthesis Simulation is deferent from Behavioral Simulatio

Thanks TrickyDicky,

The always block is always called on the signals in the sensitivity list. You should have always @(*)
I use a spacial protocol in my cache module. it all starts with rqst_i signal from Prefetch unit, then cache unit will check for address to see if it needs to be fetched from the main memory, then the cache will raise an ack_o signal to notify Prefetch unit that the data is ready to fetch, and at the end rqst_i will be off and cause the ack_o signal to be off too.
So I only need to put rst_i, rqst_i and ex_rdy_i (which is an informant signal from MMU) on the sensitivity list. But I think the Vivado just adds the other signals during synthesis process!!!

You should also use all non-blocking assignments rather than blocking..
Is there any reason to do so?

But the use of logic without a clock is poor practice. You current code creates latches, which will cause you timing problems.
I understood such thing during the project and I realized that it's tooooo late to change :sad::sad:.

Thanks a lot Dicky

P.S. Sorry for my bad English...
 

Re: Why the result of Post-Synthesis Simulation is deferent from Behavioral Simulatio

Thanks TrickyDicky,


I use a spacial protocol in my cache module. it all starts with rqst_i signal from Prefetch unit, then cache unit will check for address to see if it needs to be fetched from the main memory, then the cache will raise an ack_o signal to notify Prefetch unit that the data is ready to fetch, and at the end rqst_i will be off and cause the ack_o signal to be off too.
So I only need to put rst_i, rqst_i and ex_rdy_i (which is an informant signal from MMU) on the sensitivity list. But I think the Vivado just adds the other signals during synthesis process!!!

Vivado will ignore sensitivity lists as it has to make real logic. It does this by examining the code and using everything in the always block to make the logic as it requires.
 
  • Like
Reactions: manili

    manili

    Points: 2
    Helpful Answer Positive Rating
Re: Why the result of Post-Synthesis Simulation is deferent from Behavioral Simulatio

Vivado will ignore sensitivity lists as it has to make real logic. It does this by examining the code and using everything in the always block to make the logic as it requires.

Ergo, your code is simulating incorrectly due to the missing signals in the sensitivity list, the synthesized logic has the correct simulation output.
 
  • Like
Reactions: manili

    manili

    Points: 2
    Helpful Answer Positive Rating
Re: Why the result of Post-Synthesis Simulation is deferent from Behavioral Simulatio

Thanks ads-ee,
One question : Why we can't build such logics in real world (i.e. some signals in sensitivity list)?
 

Re: Why the result of Post-Synthesis Simulation is deferent from Behavioral Simulatio

because synthesis tools have to implement the described circuit functionality, so it ignores the sensitivity list as that is a simulation function to know when the simulator should enter the always block. The reason for this is primarily to speed up simulation (you only enter the block when needed) it has nothing to do with the functionality of the code.
 
  • Like
Reactions: manili

    manili

    Points: 2
    Helpful Answer Positive Rating
Re: Why the result of Post-Synthesis Simulation is deferent from Behavioral Simulatio

I think I understood your words : "The synthesizer ignores the sensitivity list because it doesn't affect the inside of the block functionality".
But does it mean it isn't possible to implement such thing in real world ? For example my code is heavily based upon this wrong assumption and now I have to change it a lot, but if it was possible to implement this as a real logic, well my problem would be solved completely. Am I true, or I'm missing something ?
Thanks.
 

Re: Why the result of Post-Synthesis Simulation is deferent from Behavioral Simulatio

But does it mean it isn't possible to implement such thing in real world ? For example my code is heavily based upon this wrong assumption and now I have to change it a lot, but if it was possible to implement this as a real logic, well my problem would be solved completely. Am I true, or I'm missing something ?
Thanks.

It is not possible to implement such logic, i.e.: ignoring some signals that should have been in the sensitivity list.

That is why you should never use anything but always @* for combinational code.

The comment in post #5 should not be telling you to use non-blocking assignments, you are writing combinational code it should be blocking assignments. But as noted you have feedback of some of the assigned values as conditions in if statements, which will result in latches being produced. This is very very bad coding and will likely result in timing problems from run to run. You will likely have to include very specific timing constraints to ensure these latches always meet timing. There is a reason for not implementing latches in a design as it's very hard to build timing constraints for them.
 
  • Like
Reactions: manili

    manili

    Points: 2
    Helpful Answer Positive Rating
Re: Why the result of Post-Synthesis Simulation is deferent from Behavioral Simulatio

Thank you very much ads-ee, it was very helpful.
Are there any books which can help me to learn how to write RTL code and also includes these details ?
 

Re: Why the result of Post-Synthesis Simulation is deferent from Behavioral Simulatio

Thank you very much ads-ee, it was very helpful.
Are there any books which can help me to learn how to write RTL code and also includes these details ?

Unfortunately not many...I do think there are a few that might be good, but I've had them on my Amazon To Buy list for approximately 3+ years. I see no need to buy a book that will teach me what I already know ;-)

Just look around Amazon for books with titles that have the keywords like Verilog, Design, etc.

This is the particular book I was interested in: https://www.amazon.com/Advanced-Design-Practical-Examples-Verilog/dp/1482593335/ref=sr_1_2?ie=UTF8&qid=1483489438&sr=8-2&keywords=verilog+example
 
  • Like
Reactions: manili

    manili

    Points: 2
    Helpful Answer Positive Rating
Re: Why the result of Post-Synthesis Simulation is deferent from Behavioral Simulatio

This has always been a complaint of mine -- most books are written for the extreme beginner and don't have enough depth. Other books provide advise that is not longer relevant -- assumptions about tools that are no longer valid. Even among professionals, there is a huge difference in what is considered "good code".

My favorite resource is probably the Altera "Advanced Synthesis Cookbook", which is freely available and includes code samples. It is easily found on google. It is a bit old, but the examples are practical and contain explanations for why the code is written in a specific manner.
 
  • Like
Reactions: manili

    manili

    Points: 2
    Helpful Answer Positive Rating
Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top