Author Topic: Vivado pre synthesis sim works but post has logic removed making it not work!  (Read 8679 times)

0 Members and 1 Guest are viewing this topic.

Offline BoscoeTopic starter

  • Frequent Contributor
  • **
  • Posts: 276
So i'm trying to complete a project in Vivado but finding it difficult. I have used Quartus in the past.

I have some HDL that sims correctly in behavioral simulation but once it has been synthesized by Vivado I get warnings saying nearly 100 registers haven't been and thus removed but now it doesn't work! In behavioral sim I look at the registers being removed by synthesis and they indeed being used. I have posted a question on the Xilinx forums but they are awfully slow. I wonder if anyone here has any suggestions?The code is partially written to interface with an image sensor and the part being tested is the serial update of the registers. I have a couple of state machines - one for the SPI clocking the data out and another to assign the write data to the SPI module and create pulses to start the SPI state machine. In the behavioral sim everything seems to work however in post synth sim the SPI module seems never to be reached. I've gone through the reports in Vivado trying to track down which register might not be being reached (timing error) but as there's little information there it's very difficult. Also, look at the pre synth sim I have been careful to add basic extra clock cycles to accommodate for that sort of thing. Basically I'm left scratching my head! Code below.

I have also simed the modules individually and they work fine.

Any help would be awesome! Thanks


Code: [Select]
[Synth 8-3332] Sequential element (sclk_en_reg) is unused and will be removed from module spi_16bit.

[Synth 8-3332] Sequential element (spi_data_reg) is unused and will be removed from module spi_16bit.

[Synth 8-3332] Sequential element (state_reg) is unused and will be removed from module spi_16bit.

[Synth 8-3332] Sequential element (\data_stage_reg[15] ) is unused and will be removed from module spi_16bit.

[Synth 8-3332] Sequential element (\data_stage_reg[14] ) is unused and will be removed from module spi_16bit.

[Synth 8-3332] Sequential element (\data_stage_reg[13] ) is unused and will be removed from module spi_16bit.

[Synth 8-3332] Sequential element (\data_stage_reg[12] ) is unused and will be removed from module spi_16bit.

[Synth 8-3332] Sequential element (\data_stage_reg[11] ) is unused and will be removed from module spi_16bit.

[Synth 8-3332] Sequential element (\data_stage_reg[10] ) is unused and will be removed from module spi_16bit.

[Synth 8-3332] Sequential element (\data_stage_reg[9] ) is unused and will be removed from module spi_16bit.

[Synth 8-3332] Sequential element (\data_stage_reg[8] ) is unused and will be removed from module spi_16bit.

[Synth 8-3332] Sequential element (\data_stage_reg[7] ) is unused and will be removed from module spi_16bit.

[Synth 8-3332] Sequential element (\data_stage_reg[6] ) is unused and will be removed from module spi_16bit.

[Synth 8-3332] Sequential element (\data_stage_reg[5] ) is unused and will be removed from module spi_16bit.

[Synth 8-3332] Sequential element (\data_stage_reg[4] ) is unused and will be removed from module spi_16bit.

[Synth 8-3332] Sequential element (\data_stage_reg[3] ) is unused and will be removed from module spi_16bit.

[Synth 8-3332] Sequential element (\data_stage_reg[2] ) is unused and will be removed from module spi_16bit.

[Synth 8-3332] Sequential element (\data_stage_reg[1] ) is unused and will be removed from module spi_16bit.

[Synth 8-3332] Sequential element (\data_stage_reg[0] ) is unused and will be removed from module spi_16bit.

[Synth 8-3332] Sequential element (\int_spi_data_reg[15] ) is unused and will be removed from module spi_16bit.

[Synth 8-3332] Sequential element (\int_spi_data_reg[14] ) is unused and will be removed from module spi_16bit.

[Synth 8-3332] Sequential element (\int_spi_data_reg[13] ) is unused and will be removed from module spi_16bit.

[Synth 8-3332] Sequential element (\int_spi_data_reg[12] ) is unused and will be removed from module spi_16bit.

[Synth 8-3332] Sequential element (\int_spi_data_reg[11] ) is unused and will be removed from module spi_16bit.

[Synth 8-3332] Sequential element (\int_spi_data_reg[10] ) is unused and will be removed from module spi_16bit.

[Synth 8-3332] Sequential element (\int_spi_data_reg[9] ) is unused and will be removed from module spi_16bit.

[Synth 8-3332] Sequential element (\int_spi_data_reg[8] ) is unused and will be removed from module spi_16bit.

[Synth 8-3332] Sequential element (\int_spi_data_reg[7] ) is unused and will be removed from module spi_16bit.

[Synth 8-3332] Sequential element (\int_spi_data_reg[6] ) is unused and will be removed from module spi_16bit.

[Synth 8-3332] Sequential element (\int_spi_data_reg[5] ) is unused and will be removed from module spi_16bit.

[Synth 8-3332] Sequential element (\int_spi_data_reg[4] ) is unused and will be removed from module spi_16bit.

[Synth 8-3332] Sequential element (\int_spi_data_reg[3] ) is unused and will be removed from module spi_16bit.

[Synth 8-3332] Sequential element (\int_spi_data_reg[2] ) is unused and will be removed from module spi_16bit.

[Synth 8-3332] Sequential element (\int_spi_data_reg[1] ) is unused and will be removed from module spi_16bit.

[Synth 8-3332] Sequential element (\int_spi_data_reg[0] ) is unused and will be removed from module spi_16bit.

[Synth 8-3332] Sequential element (\trans_state_reg[1] ) is unused and will be removed from module ibis_reg_update.

[Synth 8-3332] Sequential element (\spi_data_reg_reg[15] ) is unused and will be removed from module ibis_reg_update.

[Synth 8-3332] Sequential element (\spi_data_reg_reg[14] ) is unused and will be removed from module ibis_reg_update.

[Synth 8-3332] Sequential element (\spi_data_reg_reg[13] ) is unused and will be removed from module ibis_reg_update.

[Synth 8-3332] Sequential element (\spi_data_reg_reg[12] ) is unused and will be removed from module ibis_reg_update.

[Synth 8-3332] Sequential element (\spi_data_reg_reg[11] ) is unused and will be removed from module ibis_reg_update.

[Synth 8-3332] Sequential element (\spi_data_reg_reg[10] ) is unused and will be removed from module ibis_reg_update.

[Synth 8-3332] Sequential element (\spi_data_reg_reg[9] ) is unused and will be removed from module ibis_reg_update.

[Synth 8-3332] Sequential element (\spi_data_reg_reg[8] ) is unused and will be removed from module ibis_reg_update.

[Synth 8-3332] Sequential element (\spi_data_reg_reg[7] ) is unused and will be removed from module ibis_reg_update.

[Synth 8-3332] Sequential element (\spi_data_reg_reg[6] ) is unused and will be removed from module ibis_reg_update.

[Synth 8-3332] Sequential element (\spi_data_reg_reg[5] ) is unused and will be removed from module ibis_reg_update.

[Synth 8-3332] Sequential element (\spi_data_reg_reg[4] ) is unused and will be removed from module ibis_reg_update.

[Synth 8-3332] Sequential element (\spi_data_reg_reg[3] ) is unused and will be removed from module ibis_reg_update.

[Synth 8-3332] Sequential element (\spi_data_reg_reg[2] ) is unused and will be removed from module ibis_reg_update.

[Synth 8-3332] Sequential element (\spi_data_reg_reg[1] ) is unused and will be removed from module ibis_reg_update.

[Synth 8-3332] Sequential element (\spi_data_reg_reg[0] ) is unused and will be removed from module ibis_reg_update.

[Synth 8-3332] Sequential element (\ibis_regs_reg[0][11] ) is unused and will be removed from module ibis_reg_update.

[Synth 8-3332] Sequential element (\ibis_regs_reg[0][10] ) is unused and will be removed from module ibis_reg_update.

[Synth 8-3332] Sequential element (\ibis_regs_reg[0][9] ) is unused and will be removed from module ibis_reg_update.

[Synth 8-3332] Sequential element (\ibis_regs_reg[0][8] ) is unused and will be removed from module ibis_reg_update.

[Synth 8-3332] Sequential element (\ibis_regs_reg[0][7] ) is unused and will be removed from module ibis_reg_update.

[Synth 8-3332] Sequential element (\ibis_regs_reg[0][6] ) is unused and will be removed from module ibis_reg_update.

[Synth 8-3332] Sequential element (\ibis_regs_reg[0][5] ) is unused and will be removed from module ibis_reg_update.

[Synth 8-3332] Sequential element (\ibis_regs_reg[0][4] ) is unused and will be removed from module ibis_reg_update.

[Synth 8-3332] Sequential element (\ibis_regs_reg[0][3] ) is unused and will be removed from module ibis_reg_update.

[Synth 8-3332] Sequential element (\ibis_regs_reg[0][2] ) is unused and will be removed from module ibis_reg_update.

[Synth 8-3332] Sequential element (\ibis_regs_reg[0][1] ) is unused and will be removed from module ibis_reg_update.

[Synth 8-3332] Sequential element (\ibis_regs_reg[0][0] ) is unused and will be removed from module ibis_reg_update.

[Synth 8-3332] Sequential element (\ibis_regs_reg[1][11] ) is unused and will be removed from module ibis_reg_update.

[Synth 8-3332] Sequential element (\ibis_regs_reg[1][10] ) is unused and will be removed from module ibis_reg_update.

[Synth 8-3332] Sequential element (\ibis_regs_reg[1][9] ) is unused and will be removed from module ibis_reg_update.

[Synth 8-3332] Sequential element (\ibis_regs_reg[1][8] ) is unused and will be removed from module ibis_reg_update.

[Synth 8-3332] Sequential element (\ibis_regs_reg[1][7] ) is unused and will be removed from module ibis_reg_update.

[Synth 8-3332] Sequential element (\ibis_regs_reg[1][6] ) is unused and will be removed from module ibis_reg_update.

[Synth 8-3332] Sequential element (\ibis_regs_reg[1][5] ) is unused and will be removed from module ibis_reg_update.

[Synth 8-3332] Sequential element (\ibis_regs_reg[1][4] ) is unused and will be removed from module ibis_reg_update.

[Synth 8-3332] Sequential element (\ibis_regs_reg[1][3] ) is unused and will be removed from module ibis_reg_update.

[Synth 8-3332] Sequential element (\ibis_regs_reg[1][2] ) is unused and will be removed from module ibis_reg_update.

[Synth 8-3332] Sequential element (\ibis_regs_reg[1][1] ) is unused and will be removed from module ibis_reg_update.

[Synth 8-3332] Sequential element (\ibis_regs_reg[1][0] ) is unused and will be removed from module ibis_reg_update.

[Synth 8-3332] Sequential element (\ibis_regs_reg[2][11] ) is unused and will be removed from module ibis_reg_update.

[Synth 8-3332] Sequential element (\ibis_regs_reg[2][10] ) is unused and will be removed from module ibis_reg_update.

[Synth 8-3332] Sequential element (\ibis_regs_reg[2][9] ) is unused and will be removed from module ibis_reg_update.

[Synth 8-3332] Sequential element (\ibis_regs_reg[2][8] ) is unused and will be removed from module ibis_reg_update.

[Synth 8-3332] Sequential element (\ibis_regs_reg[2][7] ) is unused and will be removed from module ibis_reg_update.

[Synth 8-3332] Sequential element (\ibis_regs_reg[2][6] ) is unused and will be removed from module ibis_reg_update.

[Synth 8-3332] Sequential element (\ibis_regs_reg[2][5] ) is unused and will be removed from module ibis_reg_update.

[Synth 8-3332] Sequential element (\ibis_regs_reg[2][4] ) is unused and will be removed from module ibis_reg_update.

[Synth 8-3332] Sequential element (\ibis_regs_reg[2][3] ) is unused and will be removed from module ibis_reg_update.

[Synth 8-3332] Sequential element (\ibis_regs_reg[2][2] ) is unused and will be removed from module ibis_reg_update.

[Synth 8-3332] Sequential element (\ibis_regs_reg[2][1] ) is unused and will be removed from module ibis_reg_update.

[Synth 8-3332] Sequential element (\ibis_regs_reg[2][0] ) is unused and will be removed from module ibis_reg_update.

[Synth 8-3332] Sequential element (\ibis_regs_reg[4][11] ) is unused and will be removed from module ibis_reg_update.

[Synth 8-3332] Sequential element (\ibis_regs_reg[4][10] ) is unused and will be removed from module ibis_reg_update.

[Synth 8-3332] Sequential element (\ibis_regs_reg[4][9] ) is unused and will be removed from module ibis_reg_update.

[Synth 8-3332] Sequential element (\ibis_regs_reg[4][8] ) is unused and will be removed from module ibis_reg_update.

[Synth 8-3332] Sequential element (\ibis_regs_reg[4][7] ) is unused and will be removed from module ibis_reg_update.

[Synth 8-3332] Sequential element (\ibis_regs_reg[4][6] ) is unused and will be removed from module ibis_reg_update.

[Synth 8-3332] Sequential element (\ibis_regs_reg[4][5] ) is unused and will be removed from module ibis_reg_update.

[Synth 8-3332] Sequential element (\ibis_regs_reg[4][4] ) is unused and will be removed from module ibis_reg_update.

[Synth 8-3332] Sequential element (\ibis_regs_reg[4][3] ) is unused and will be removed from module ibis_reg_update.

[Synth 8-3332] Sequential element (\ibis_regs_reg[4][2] ) is unused and will be removed from module ibis_reg_update.

[Synth 8-3332] Sequential element (\ibis_regs_reg[4][1] ) is unused and will be removed from module ibis_reg_update.

[Synth 8-3332] Sequential element (\ibis_regs_reg[4][0] ) is unused and will be removed from module ibis_reg_update.

 

Offline BoscoeTopic starter

  • Frequent Contributor
  • **
  • Posts: 276
Code

Code: [Select]
/*
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[1] = 12'b000111100000; //reg_nrof_pixels 01 480 pixels
ibis_regs[2] = 12'b001010000000; //reg_nrof_lines 02 640 lines
ibis_regs[3] = 12'b000000000000; //reg_int_time 03 Not done \/ \/
ibis_regs[4] = 12'b000000000011; //reg_delay 04
ibis_regs[5] = 12'b000000000000; //reg_x_reg 05
ibis_regs[6] = 12'b000000000000; //reg_y_reg 06
ibis_regs[7] = 12'b000000000000; //reg_img_core_reg 07
ibis_regs[8] = 12'b000000010000; //reg_amp_reg 08
ibis_regs[9] = 12'b000000000000; //reg_dac_raw_reg 09
ibis_regs[10] = 12'b000000000000; //reg_dac_fine_reg 10
ibis_regs[11] = 12'b000000000000; //reg_dac_dark_reg 11
ibis_regs[12] = 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

Code: [Select]
/*
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

Code: [Select]
/*
Pulse generator creates a pulse of 'n' number of 'clk' cycles.



*/
module pulse_gen (
//Inputs
input logic  in_edge,
clk,



//Output
output logic out_pulse
);

reg r1 = 0, r2 = 0, r3 = 0, r4 = 0;

always_ff @ (posedge clk)
begin
r1 <= in_edge;  // first stage of 2-stage synchronizer
        r2 <= r1;       // second stage of 2-stage synchronizer
        r3 <= r2;       // edge detector memory
        r4 <= r3;
end

assign out_pulse = r2 & ~r4;


endmodule
 

Offline filssavi

  • Frequent Contributor
  • **
  • Posts: 433
Usually when vivado removes logic (registers but not only) he does that because as the code is written they will never switch

I had your same issue as you before and the main problem is that in behavioural mode the simulator executes pretty much anything you throw at it (even if it isn't synthetizable), synth is a lot more picky about the code

So I think that register deletion per se is not the cause, it is indeed the effect, the true problem lurks somewhere in your code
 

Offline rstofer

  • Super Contributor
  • ***
  • Posts: 9889
  • Country: us
Does your logic ultimately wind up at a pin?  If not, it's removed and everything that provides logic to create that signal, all the way up the chain, is removed as well.  There can be layers and layers of logic that ultimately wiggle MOSI (for example) but if MOSI isn't assigned to a pin, it's all removed.

Something like that...
 

Offline 6thimage

  • Regular Contributor
  • *
  • Posts: 181
  • Country: gb
Have you read the entirety of the synthesis report? Whenever logic is being removed, the synthesis tool will give a reason, it might only be one line (i.e. an enable line being constantly low for a module will result in the entire module being removed). I have quickly thrown your 3 files into vivado and got this under the cross boundary optimisation section in the synthesis report (line 163 and 164 from vivado 2015.4):
Code: [Select]
WARNING: [Synth 8-3917] design ibis_reg_update has port spi_data driven by constant 0
WARNING: [Synth 8-3917] design ibis_reg_update has port spi_clk driven by constant 0

If you change (in ibis_reg_update)
Code: [Select]
output logic  spi_data = 0, spi_clk = 0, reg_clk = 0,
to
Code: [Select]
output logic  spi_data, spi_clk, reg_clk = 0,
this warning is not generated and the utilisation goes from 89 LUTs and 62 registers to 104 LUTS and 82 registers (artix-7). Whether this fixes your problem is something else (I haven't had much of a chance to use system verilog yet, as I'm currently working with spartan 6 devices).

Also, you generate clocks from logic, which is generally not a good idea. It is much better to have an enable signal for a higher speed clock. So instead of creating the spi clock by dividing the input clk by 10, make it so that it produces an enable pulse every 10 clocks that only lasts one clock. It will improve the timing characteristics of the design and will probably require less resources. Additionally, with the intelligent clock gating in most synthesis tools, it will consume less dynamic power.

I'm also surprised that
Code: [Select]
always_ff @ (posedge config_latch)
works, as config_latch will be treated as a clock, which is unlikely to be what you want and could cause metastability (if config_latch is not synchronous with your other clocks).
 

Offline BoscoeTopic starter

  • Frequent Contributor
  • **
  • Posts: 276
Does your logic ultimately wind up at a pin?  If not, it's removed and everything that provides logic to create that signal, all the way up the chain, is removed as well.  There can be layers and layers of logic that ultimately wiggle MOSI (for example) but if MOSI isn't assigned to a pin, it's all removed.

Something like that...

It does and doesn't work I'm afraid.
 

Offline BoscoeTopic starter

  • Frequent Contributor
  • **
  • Posts: 276
Have you read the entirety of the synthesis report? Whenever logic is being removed, the synthesis tool will give a reason, it might only be one line (i.e. an enable line being constantly low for a module will result in the entire module being removed). I have quickly thrown your 3 files into vivado and got this under the cross boundary optimisation section in the synthesis report (line 163 and 164 from vivado 2015.4):
Code: [Select]
WARNING: [Synth 8-3917] design ibis_reg_update has port spi_data driven by constant 0
WARNING: [Synth 8-3917] design ibis_reg_update has port spi_clk driven by constant 0

If you change (in ibis_reg_update)
Code: [Select]
output logic  spi_data = 0, spi_clk = 0, reg_clk = 0,
to
Code: [Select]
output logic  spi_data, spi_clk, reg_clk = 0,
this warning is not generated and the utilisation goes from 89 LUTs and 62 registers to 104 LUTS and 82 registers (artix-7). Whether this fixes your problem is something else (I haven't had much of a chance to use system verilog yet, as I'm currently working with spartan 6 devices).

Also, you generate clocks from logic, which is generally not a good idea. It is much better to have an enable signal for a higher speed clock. So instead of creating the spi clock by dividing the input clk by 10, make it so that it produces an enable pulse every 10 clocks that only lasts one clock. It will improve the timing characteristics of the design and will probably require less resources. Additionally, with the intelligent clock gating in most synthesis tools, it will consume less dynamic power.

I'm also surprised that
Code: [Select]
always_ff @ (posedge config_latch)
works, as config_latch will be treated as a clock, which is unlikely to be what you want and could cause metastability (if config_latch is not synchronous with your other clocks).

Thanks for your reply - it's helpful.

The thing is even when in simulation of just the spa module it still doesn't work and baffles me! I have rewritten the module to somethings a lot more wordy but very explicit. Now the SCLK is output in the simulation however the SDATA is not! Even when the pins are driven as constants through the state machine it still doesn't work!

Code: [Select]
/*
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,
spi_data,
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 == 4)
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 = 0;
logic [5:0] state = 0;

//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

//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;
end

else
begin
case(state)
0: begin
if(output_pulse == 1)
begin
state <= 1;
busy <= 1;
end

else
begin
busy <= 0;
spi_sclk <= 0;
end
end

//15th bit in the data
1: begin
spi_data <= int_spi_data[15];
spi_sclk <= 0;
state++;
end

2: begin
spi_sclk <= 1;
state++;
end

//14th bit in the data
3: begin
spi_data <= int_spi_data[14];
spi_sclk <= 0;
state++;
end

4: begin
spi_sclk <= 1;
state++;
end

//13th bit in the data
5: begin
spi_data <= int_spi_data[13];
spi_sclk <= 0;
state++;
end

6: begin
spi_sclk <= 1;
state++;
end

//12th bit in the data
7: begin
spi_data <= int_spi_data[12];
spi_sclk <= 0;
state++;
end

8: begin
spi_sclk <= 1;
state++;
end

//11th bit in the data
9: begin
spi_data <= int_spi_data[11];
spi_sclk <= 0;
state++;
end

10: begin
spi_sclk <= 1;
state++;
end

//10th bit in the data
11: begin
spi_data <= int_spi_data[10];
spi_sclk <= 0;
state++;
end

12: begin
spi_sclk <= 1;
state++;
end

//9th bit in the data
13: begin
spi_data <= int_spi_data[9];
spi_sclk <= 0;
state++;
end

14: begin
spi_sclk <= 1;
state++;
end

//8th bit in the data
15: begin
spi_data <= int_spi_data[8];
spi_sclk <= 0;
state++;
end

16: begin
spi_sclk <= 1;
state++;
end

//7th bit in the data
17: begin
spi_data <= int_spi_data[7];
spi_sclk <= 0;
state++;
end

18: begin
spi_sclk <= 1;
state++;
end

//6th bit in the data
19: begin
spi_data <= int_spi_data[6];
spi_sclk <= 0;
state++;
end

20: begin
spi_sclk <= 1;
state++;
end

//5th bit in the data
21: begin
spi_data <= int_spi_data[5];
spi_sclk <= 0;
state++;
end

22: begin
spi_sclk <= 1;
state++;
end

//4th bit in the data
23: begin
spi_data <= int_spi_data[4];
spi_sclk <= 0;
state++;
end

24: begin
spi_sclk <= 1;
state++;
end

//3rd bit in the data
25: begin
spi_data <= int_spi_data[3];
spi_sclk <= 0;
state++;
end

26: begin
spi_sclk <= 1;
state++;
end

//2nd bit in the data
27: begin
spi_data <= int_spi_data[2];
spi_sclk <= 0;
state++;
end

28: begin
spi_sclk <= 1;
state++;
end

//1st bit in the data
29: begin
spi_data <= int_spi_data[1];
spi_sclk <= 0;
state++;
end

30: begin
spi_sclk <= 1;
state++;
end

//0th bit in the data
31: begin
spi_data <= int_spi_data[0];
spi_sclk <= 0;
state++;
end

32: begin
spi_sclk <= 1;
state <= 0;
end
endcase
end
end
endmodule
 

Offline BoscoeTopic starter

  • Frequent Contributor
  • **
  • Posts: 276
PS I tried changing the initial values assign the silk and data signals but it didn't work :(.

Attached is the output of the sim for the above code.
 

Offline kfnight

  • Regular Contributor
  • *
  • Posts: 71
This probably won't fix your problem, but your flip-flops are using a combination of blocking and non-blocking assignments. Usually non-blocking assignments are used exclusively within flip-flips. So code like this

Code: [Select]
//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

should be like

Code: [Select]
//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++;
                             clock_div <= clock_div + 1;
end
end

This also highlights a SystemVerilog gotcha. The C-style increment and decrement operators behave as blocking assignments, so clock_div++ is equivalent to clock_div = clock_div + 1.
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf