UPGRADE YOUR BROWSER

We have detected your current browser version is not the latest one. Xilinx.com uses the latest web technologies to bring you the best online experience possible. Please upgrade to a Xilinx.com supported browser:Chrome, Firefox, Internet Explorer 11, Safari. Thank you!

cancel
Showing results for 
Search instead for 
Did you mean: 
Highlighted
Visitor boscoe
Visitor
8,905 Views
Registered: ‎01-28-2016

Project works in simulation but necessary parts are removed when synthesized.

So a part of my project updates an image sensor which register values over SPI. I wrote the SPI module which is synthesized out of the project despite the fact it's necessary for the project to work. In simulation if functions correctly how ever after synthesis it doesn't. can someone help me understand why this is happening? Thanks!

 

/*
	A module to update the registers in the ibis4_6600 image sensor.

	Now need to:
	- add a facilty to create custom register values based on the 'config_data'.
	- add busy line.
*/	
module ibis_reg_update (	
							//clock and reset
							input logic			clk_200M, nrst,

							//Input data capture and latch
							input logic  [31:0]	config_data,
							input logic			config_latch,

							//SPI connections
							output logic		spi_data = 0, spi_clk = 0, reg_clk = 0,

							//Status output
							output logic		busy


						);

	/*	Variables correspoding to the IBIS4 config registers.
		Defaults set for 30fps video at 640x480 pixels.

	*/	

	logic	[11:0]ibis_regs[13] = '{	//Default value		  Reg Name 			Addr 	Notes
										12'b000000000000,	//reg_sequencer 	00		All normal
										12'b000111100000,	//reg_nrof_pixels 	01		480	pixels
										12'b001010000000,	//reg_nrof_lines 	02		640 lines
										12'b000000000000,	//reg_int_time 		03		Not done \/ \/
										12'b000000000011,	//reg_delay			04
										12'b000000000000,	//reg_x_reg			05
										12'b000000000000,	//reg_y_reg			06
										12'b000000000000,	//reg_img_core_reg 	07
										12'b000000010000,	//reg_amp_reg		08
										12'b000000000000,	//reg_dac_raw_reg	09
										12'b000000000000,	//reg_dac_fine_reg 	10
										12'b000000000000,	//reg_dac_dark_reg 	11
										12'b000000000000	//reg_adc_reg 		12
	};
	


	logic	[3:0]	reg_addr = 0;
	logic	[7:0]	clock_div = 0;
	logic 			start_pulse, reg_upd_clk = 0, spi_latch, spi_busy;
	logic 	[1:0]	trans_state = 0;

	logic	[15:0]	spi_data_reg = 0, reg_upd_counter = 0;

	//Generate 10MHz 'reg_upd_clk'
	always_ff @ (posedge clk_200M or negedge nrst)
	begin
		//Reset
		if(nrst == 0)
		begin
			reg_upd_clk = 0;
			clock_div = 0;
		end

		//Generate clock
		else
		begin
			if(clock_div == 9)
			begin
				reg_upd_clk <= ~reg_upd_clk;
				clock_div <= 0;
			end

			else clock_div++;
		end
	end

	//Latch the 'config_data' into the current memeory
	always_ff @ (posedge config_latch)
	begin
		if(config_data == 0)
		begin
							//Default value		  Reg Name 			Addr 	Notes
			ibis_regs[0] = 	12'b000000000000;	//reg_sequencer 	00		All normal
			ibis_regs[0] = 	12'b000111100000;	//reg_nrof_pixels 	01		480	pixels
			ibis_regs[0] = 	12'b001010000000;	//reg_nrof_lines 	02		640 lines
			ibis_regs[0] = 	12'b000000000000;	//reg_int_time 		03		Not done \/ \/
			ibis_regs[0] = 	12'b000000000011;	//reg_delay			04
			ibis_regs[0] = 	12'b000000000000;	//reg_x_reg			05
			ibis_regs[0] = 	12'b000000000000;	//reg_y_reg			06
			ibis_regs[0] = 	12'b000000000000;	//reg_img_core_reg 	07
			ibis_regs[0] = 	12'b000000010000;	//reg_amp_reg		08
			ibis_regs[0] = 	12'b000000000000;	//reg_dac_raw_reg	09
			ibis_regs[0] = 	12'b000000000000;	//reg_dac_fine_reg 	10
			ibis_regs[0] = 	12'b000000000000;	//reg_dac_dark_reg 	11
			ibis_regs[0] = 	12'b000000000000;	//reg_adc_reg 		12
		end
	end

	//Start the register update sequence
	always_ff @ (negedge reg_upd_clk or negedge nrst)
	begin
		//Reset 
		if(nrst == 0)
		begin
			trans_state = 0;
			reg_upd_counter = 0;
			spi_latch = 0;
			reg_clk = 0;
			reg_addr = 0;
		end
		//Run
		else
		begin
			case(trans_state)
				//Wait for the start pulse to start the transmission
				0: begin
					if(start_pulse == 1) trans_state = 1;
				end

				1: begin
					//Reset the counter after 25 clock cycles
					if(reg_upd_counter == 25)
					begin
						reg_upd_counter <= 0;
					end

					else
					begin
						//increment the counter
						reg_upd_counter++;

						case(reg_upd_counter)
							1: 	begin
								spi_data_reg[15:12] <= reg_addr;
								spi_data_reg[11:0]	<= ibis_regs[reg_addr];
							end

							2: 	begin
								//Start the SPI transmission for 'reg_addr'.
								spi_latch <= 1;
							end

							5: 	begin
								spi_latch <= 0;
							end

							23: begin
								//Latch the data int othe image sensor with 'reg_clk'.
								reg_clk <= 1;
							end

							24: begin
								//Repeat 13 times incrementing 'reg_addr' each time.
								reg_clk <= 0;

								if(reg_addr == 12)
								begin
									trans_state <= 0;
									reg_addr <= 0;
								end

								else
								begin
									reg_addr++;
								end
							end
						endcase
					end
				end
			endcase
		end
	end

	pulse_gen gen0(	.in_edge(config_latch), .clk(reg_upd_clk), .out_pulse(start_pulse));

	spi_16bit spi0(	.clk_200M(clk_200M), .nrst(nrst),

					.data_in(spi_data_reg),
					.data_latch(spi_latch),

					.spi_sclk(spi_clk), 
					.spi_data(spi_data),
					.busy(spi_busy));

	assign busy = spi_busy | trans_state;
	

endmodule

 

/*
	A regular SPI hardware module to send a 16bit number at 10MHz with a 200MHz master clock.
	

*/
module spi_16bit(	//Input control
					input logic			clk_200M, nrst,


					//Input data
					input logic  [15:0] data_in,
					input logic 		data_latch,

					//Output pins
					output logic		spi_sclk = 0, 
										spi_data = 0,
										busy
	);

	/*
		Generate the 10MHz SCLK
	*/
	logic [3:0]		clk_divider = 0;
	logic			int_spi_clk = 0;

	always_ff @ (posedge clk_200M or negedge nrst)
	begin
		//Reset
		if(nrst == 0)
		begin
			clk_divider = 0;
		end

		//Normal Operation
		else
		begin
			if(clk_divider == 9)
			begin
				clk_divider = 0;
				int_spi_clk = ~int_spi_clk;
			end

			else
			begin
				clk_divider++;
			end
		end
	end

	/*
		Send the data out on the spi pin
	*/
	logic [15:0]	int_spi_data;
	logic 			state = 0, sclk_en = 0;
	logic [15:0]	data_stage = 16;

	assign busy = state;

	//Capture the input data on the rising edge of 'data_latch'
	always_ff @ (posedge data_latch or negedge nrst)
	begin
		if(nrst == 0)
		begin
			int_spi_data = 0;
		end

		else
		begin
			int_spi_data = data_in;
		end
	end

	always_comb
	begin
		if(sclk_en == 1)	spi_sclk = int_spi_clk;
		else spi_sclk = 0;
	end

	//Generates a starting pulse for the data transmission
	pulse_gen	gen0(.in_edge(data_latch), .clk(int_spi_clk), .out_pulse(output_pulse));

	//Clock the data out
	always_ff @ (negedge int_spi_clk or negedge nrst)
	begin
		if(nrst == 0)
		begin
			state = 0; 
			sclk_en = 0;
			data_stage = 16;
		end

		else
		begin
			case(state)

				0: begin
					if(output_pulse == 1)
					begin
						state = 1;
					end
				end

				1: begin
					if(data_stage == 0)
					begin
						state <= 0;
						sclk_en <= 0;
						data_stage <= 16;
					end

					else
					begin
						sclk_en <= 1;
						spi_data <= int_spi_data[data_stage - 1];
						data_stage--;
					end
				end
			endcase	
		end	
	end
endmodule
Tags (2)
0 Kudos
7 Replies
Moderator
Moderator
8,900 Views
Registered: ‎07-21-2014

Re: Project works in simulation but necessary parts are removed when synthesized.

@boscoe

 

Can you share the testbench and the list of changes in behaviour. Snapshots will be very helpful.

Did you check the synthesis log for warnings?

 

Thanks,
Anusheel
-----------------------------------------------------------------------------------------------
Search for documents/answer records related to your device and tool before posting query on forums.
Search related forums and make sure your query is not repeated.

Please mark the post as an answer "Accept as solution" in case it helps to resolve your query.
Helpful answer -> Give Kudos
-----------------------------------------------------------------------------------------------

 

0 Kudos
Visitor boscoe
Visitor
8,894 Views
Registered: ‎01-28-2016

Re: Project works in simulation but necessary parts are removed when synthesized.

Thanks for the reply. There's a couple more levels but still simple.

 

ibis4_interface initialises ibis_reg_update

 

module ibis4_interface	(	
							input logic			clk_200M, nrst,
							//Internal IO
							/* 	Input settings - this bus has bits corresponding to settings to be made within the 
								image sensor. A number should be placed onto the bus and then when the update signal 
								'updt_sets' the values are captured from the bus and sent to configure the sensor.

								!!!Might need more or less than 32bits!!!
								BITS[2:0]	ISO setting.

								BIT3 		Video mode - if BIT3 is set 'video_mode' is on - low res, 30fps,
											self running.

								BIT4		Set 'Pixel DS Reset' value to 3.3V if true - 2.5V if not

								BIT5		Set 'Pixel Reset' value to 3.3V if true - 2.5V if not

							*/
							input logic [31:0]  sensor_config,

							input logic 		updt_sets,

							//Rising edge on 'img_cap' returns an image (only effective when 'video_mode' == 0)
							input logic 		img_cap,

							//Data bus and output logic
							output logic [9:0]  pix_data,	//'pix_data' is valid on the rising edge of 'pic_clk'
							output logic		pix_clk,

							output logic		frame,		//Rising edge tells us there's a new frame of data
												line,		//Rising edge tells us there's a new line of data


							//Sensor Module IO
							input logic			im_eol, im_eof,
												im_pix_valid,

							input logic  [9:0]	im_data_bus,

							output logic		im_sys_clk = 0, im_sys_rst,
												im_spi_clk, im_spi_data, im_reg_clk,
												im_yclk, im_ystrt,
												im_adc_clk_ext,
												im_spi_dac_clk, im_spi_dac_data, im_spi_dac_dsrst_sync, im_spi_dac_rst_sync	

						);
	
	/*
		Initialise sensor update hardware. Create a rising edge on 'config_latch' to configure the device.
	*/
	ibis_reg_update  upd1	(	
							//clock and reset
							.clk_200M(clk_200M), .nrst(nrst),

							//Input data capture and latch
							.config_data(sensor_config),
							.config_latch(updt_sets),

							//SPI connections
							.spi_data(im_spi_data), .spi_clk(im_spi_clk), .reg_clk(im_reg_clk),

							//Status output
							.busy()
							);

endmodule

cam_devTop initialises ibis_interface

 

module cam_dev_top	(	
					//clk rst inputs
					input logic 		clk_200M, gbl_rst,

					//Memory IO
					output logic 		ram_clk, ram_cke, 
										ram_cs, ram_cas, ram_ras, ram_we,
										ram_udm, ram_ldm,

					output logic [1:0]	ram_ba,

					output logic [11:0] ram_addr,

					inout logic  [15:0]	ram_data_bus,


					//GPIO
					input logic  [15:0] gpio_input_bus,

					output logic [15:0]	gpio_output_bus,

					//Sensor Module IO
					input logic			im_eol, im_eof,
										im_pix_valid,

					input logic  [9:0]	im_data_bus,

					output logic		im_sys_clk, im_sys_rst,
										im_spi_clk, im_spi_data, im_reg_clk,
										im_yclk, im_ystrt,
										im_adc_clk_ext,
										im_spi_dac_clk, im_spi_dac_data, im_spi_dac_dsrst_sync, im_spi_dac_rst_sync,

					//FTDI IO
					input logic 		ft_clk, 
										ft_txe, ft_rxf,

					output logic 		ft_siwu = 1,
										ft_wr = 1, ft_rd = 1,
										ft_oe = 1,
										ft_wkup = 1,
										ft_rst = 1,

					output logic [1:0]	ft_be = 3,
					input logic  [1:0]	ft_gpio,
					
					inout logic  [15:0]	ft_data_bus,

					//MCU IO 16bit bus
					input logic  		stm_dir, 
										stm_cmd_data,

					output logic 		stm_clk = 0,
										stm_txe_rxf = 1'bZ,

					inout logic	 [15:0] stm_data_bus,


					//MCU SPI1
					input logic 		spi1_clk,
										spi1_mosi,

					output logic		spi1_miso,

					//MCU SPI2
					input logic 		spi2_clk,
										spi2_mosi,

					output logic		spi2_miso,

					//MCU UART1
					input logic			stm_uart1_tx,
					
					output logic		stm_uart1_rx,

					//MCU UART2
					input logic			stm_uart2_tx,
					
					output logic		stm_uart2_rx,

					//MCU GPIO
					input logic 		stm_gpio_0,

					//FTDI UART
					input logic			ft_uart_tx,

					output logic 		ft_uart_rx,

					//TFT IO
					input logic 		tft_miso, 

					output logic 		tft_mosi, tft_sclk, tft_tft_cs, tft_sd_cs,
										tft_data_cmd, 
										tft_rst
);



	//STM bidirectional port set. For stm_dir == 1, the port is an output
	logic [15:0] stm_data_bus_in;
	logic [15:0] stm_data_bus_out;

	assign stm_data_bus = stm_dir ? stm_data_bus_out : 16'bZ;
	assign stm_data_bus_in = stm_dir ? 16'bZ : stm_data_bus;
	
	//FTDI bidirection port set. For ft_oe == 1, the port is an output
	logic [15:0] ft_data_bus_in;
	logic [15:0] ft_data_bus_out;

	assign ft_data_bus = ft_oe ? ft_data_bus_out : 16'bZ;
	assign ft_data_bus_in = ft_oe ? 16'bZ : ft_data_bus;

	//Assign STM32F429ZIT6 UART1 to ft_uart
	assign stm_uart1_rx = ft_uart_tx;
	assign ft_uart_rx = stm_uart1_tx;


	logic [31:0]	timer0_counter = 0;
	logic			timer0_dn = 0;

	always_ff @ (posedge clk_200M or negedge gbl_rst)
	begin
		if(gbl_rst == 0) timer0_dn = 1;
		else 
		begin
		  if(timer0_counter == 4) timer0_dn = 1;
		  else timer0_counter++;
		end
	end


	ibis4_interface	ibi0(	
							.clk_200M(clk_200M), .nrst(gbl_rst),
							//Internal IO
							/* 	Input settings - this bus has bits corresponding to settings to be made within the 
								image sensor. A number should be placed onto the bus and then when the update signal 
								'updt_sets' the values are captured from the bus and sent to configure the sensor.

								!!!Might need more or less than 32bits!!!
								BITS[2:0]	ISO setting.

								BIT3 		Video mode - if BIT3 is set 'video_mode' is on - low res, 30fps,
											self running.

								BIT4		Set 'Pixel DS Reset' value to 3.3V if true - 2.5V if not

								BIT5		Set 'Pixel Reset' value to 3.3V if true - 2.5V if not

							*/
							.sensor_config(0),

							.updt_sets(timer0_dn),

							//Rising edge on 'img_cap' returns an image (only effective when 'video_mode' == 0)
							.img_cap(0),

							//Data bus and output logic
							.pix_data(),	//'pix_data' is valid on the rising edge of 'pic_clk'
							.pix_clk(),

							.frame(),		//Rising edge tells us there's a new frame of data
							.line(),		//Rising edge tells us there's a new line of data


							//Sensor Module IO
							.im_eol(), .im_eof(),
							.im_pix_valid(),

							.im_data_bus(),

							.im_sys_clk(), .im_sys_rst(),
							.im_spi_clk(im_spi_clk), .im_spi_data(im_spi_data), .im_reg_clk(im_reg_clk),
							.im_yclk(), .im_ystrt(),
							.im_adc_clk_ext(),
							.im_spi_dac_clk(), .im_spi_dac_data(), .im_spi_dac_dsrst_sync(), .im_spi_dac_rst_sync()	

						);







endmodule

and then the testbench: cam_dev_top_tb

 

module cam_dev_top_tb();

	logic		clk_200M = 0,
				nrst = 1,
				spi_clk, spi_data, reg_clk;



	always
	begin
		#2.5 clk_200M = ~clk_200M;
	end








	cam_dev_top	cdt1	(	
						//clk rst inputs
						.clk_200M(clk_200M), .gbl_rst(nrst),

						//Memory IO
						.ram_clk(), .ram_cke(), 
						.ram_cs(), .ram_cas(), .ram_ras(), .ram_we(),
						.ram_udm(), .ram_ldm(),

						.ram_ba(),

						.ram_addr(),

						.ram_data_bus(),


						//GPIO
						.gpio_input_bus(),

						.gpio_output_bus(),

						//Sensor Module IO
						.im_eol(), .im_eof(),
						.im_pix_valid(),

						.im_data_bus(),

						.im_sys_clk(), .im_sys_rst(),
						.im_spi_clk(spi_clk), .im_spi_data(spi_data), .im_reg_clk(reg_clk),
						.im_yclk(), .im_ystrt(),
						.im_adc_clk_ext(),
						.im_spi_dac_clk(), .im_spi_dac_data(), .im_spi_dac_dsrst_sync(), .im_spi_dac_rst_sync(),

						//FTDI IO
						.ft_clk(), 
						.ft_txe(), .ft_rxf(),

						.ft_siwu(),
						.ft_wr(), .ft_rd(),
						.ft_oe(),
						.ft_wkup(),
						.ft_rst(),

						.ft_be(),
						.ft_gpio(),
						
						.ft_data_bus(),

						//MCU IO 16bit bus
						.stm_dir(), 
						.stm_cmd_data(),

						.stm_clk(),
						.stm_txe_rxf(),

						.stm_data_bus(),


						//MCU SPI1
						.spi1_clk(),
						.spi1_mosi(),

						.spi1_miso(),

						//MCU SPI2
						.spi2_clk(),
						.spi2_mosi(),

						.spi2_miso(),

						//MCU UART1
						.stm_uart1_tx(),
						
						.stm_uart1_rx(),

						//MCU UART2
						.stm_uart2_tx(),
						
						.stm_uart2_rx(),

						//MCU GPIO
						.stm_gpio_0(),

						//FTDI UART
						.ft_uart_tx(),

						.ft_uart_rx(),

						//TFT IO
						.tft_miso(), 

						.tft_mosi(), .tft_sclk(), .tft_tft_cs(), .tft_sd_cs(),
						.tft_data_cmd(), 
						.tft_rst()
	);








endmodule

 

Behavioral sim before synthesis.PNG
Functional sim after synthesis.PNG
0 Kudos
Visitor boscoe
Visitor
8,827 Views
Registered: ‎01-28-2016

Re: Project works in simulation but necessary parts are removed when synthesized.

Could anyone help me with this?

0 Kudos
Visitor boscoe
Visitor
8,552 Views
Registered: ‎01-28-2016

Re: Project works in simulation but necessary parts are removed when synthesized.

Anyone? I'm still having issues. I've tried simulating each module induvidually from the bottom module to the top, it all works until i get the configuration I have posted here.

0 Kudos
Observer stefanwe
Observer
8,535 Views
Registered: ‎04-05-2014

Re: Project works in simulation but necessary parts are removed when synthesized.

Hi @boscoe,

 

for me it looks like your signal 'timer0_dn' in module 'cam_dev_top' is always '1' after synthesis.

As a consequence there is no start pulse for your state machine in the 'ibis_reg_update' module.

 

You should be able to confirm that by looking at these signals in your post-synthesis simulation.

0 Kudos
Observer stefanwe
Observer
8,532 Views
Registered: ‎04-05-2014

Re: Project works in simulation but necessary parts are removed when synthesized.

Hi @boscoe,

 

another suggestion is to follow the signal that is not behaving as expected down to the module it comes from.

 

Look why the module does not generate the expected behavior.

Is the clock running, is the reset deasserted, is the start pulse generated and so on.

 

By following the chain of not working modules/signals you should get to source of your problem pretty fast,

as you can investigate all signals in your simulation.

0 Kudos
Visitor boscoe
Visitor
8,516 Views
Registered: ‎01-28-2016

Re: Project works in simulation but necessary parts are removed when synthesized.

Thank you for your replies!

 

timer0_dn gors high after 5 clock cycles of the system clock and stays there in order to initialise the system. I checked it out and it does work for both the behavioral sim and post sysnthesised sim. I'm currently working on tracking down the issue and would usually work like you mentioned. I asked the question because I found it strange it worked in behavioral sim and no further, could this be due to timing issues? My 'start_pulses' miss timed with the clocks? I also wonder about the initialisation of the registers because (I'm sure) I had initialised all my variables to a value however in behavioral sim these values haven't always worked otu for some reason but they are present in the post synth sim. In the grand scheme of things I am new to digital design and Vivado so I realise this is post likely down to my naivety. 

0 Kudos