Getting back into verilog and the synth tool vomits cryptic "warnings."  - Page 1
Forum section: electronics / general

author: XFDDesign
author_rank: Frequent Contributor
timestamp: June 02, 2015, 01:19:28 am
content: Eleven years ago, I did Verilog work and had a good time of it. Life happened and I didn't do any FPGA work since then. I have a project in which I'm getting back into FPGAs and have had a few tries getting some code to work. With a few failures, I've determined that warnings are errors with the modern synthesis engines. I have, since, started from scratch with something whichshouldbe pretty straight forward (a simple SPI engine). It is 100% state machine.The precise question for where I stand right now is at the bottom. Here is the process I've been through:I get 3 identical errors:1. Bit 7 of register intState_FSM is stuck at zero (this is, of course, after the synthesizer converts my states to a one-hot design, in which the MSB [bit 7] becomes 1 in the last state).2. Register intState_FSM_i1 is stuck at zero.3. Register rdy_54 is stuck at zero.Now, if it reported everything being stuck at zero, that would tell me I screwed up with my reset signalling. But, as you will see below, it's quite literally if(reset) {} else {bulk of code}If bit 7 is "stuck at zero" that tells me that either something is wiring it to zero (which should generate blocking vs. non-blocking errors) or I never reach there. Problem is, the state before it does 1 thing and goes to the next state.As for the ready signal always being zero, the only way I can see this happening is if the state machine never reaches the state which sets the ready flag to 1.I noted that having a "default: ..." catch in the case statement seems to be a possible source of the problem, as it doesn't exist in the one-hot list. I removed it, and then I get down to two errors:WARNING - d:/projects/spi_eng.v(100): Bit 0 of Register intState is stuck at Zero. VDB-5010and later2. WARNING - logical net 'GND_net' has no load.My text books are pretty much useless for this. If I switch to the Synplify synthesis, I get completely different synthesis errors (default engine I'm using is Lattice Synthesis Engine). Does anyone have any suggestions? Any help is appreciated. Cheers!Code:module spi_engine(clk, rst, load, rdy, clr, ext_cs, ext_sdo, ext_sdi, ext_clk, inWord, outWord);input clk, rst, load,clr;output rdy;output ext_cs, ext_sdo, ext_clk;input ext_sdi;input [23:0]inWord;output [23:0]outWord;reg [7:0] intState;// 0h00 - powerup// 0h00 - idle, waiting for load to be triggered.// 0h02 - triggered system.// 0h03 - setup chip select and the shifter/// large valued registersreg [23:0] wordStorage;reg [23:0] outWord;reg [7:0] bitCounter;// Control Signalsreg rdy;reg ext_sdo, ext_cs, ext_clk;wire clr;// wire for the clear signalalways @(posedge clk)if(1==rst)begin// do reset stuff hereintState<=8'h00;rdy<=0;// not yet ready with a new word.ext_sdo<=0;ext_cs<=1;ext_clk<=0;bitCounter<=0;endelsecase(intState)// state machine business8'h00: beginwordStorage<=0;intState<=8'h01;bitCounter<=0;end8'h01:// idle state. Wait for the load pin to be asserted.if(1==load)begin// load pin is high, this is the start of a transaction.wordStorage<=inWord; // copy the word appearing on the input pins.intState<=8'h02; // next state.end// do nothing if we haven't hit the load assertion.8'h02:// triggered state. Now we begin the whole business.begin// start by setting up chip-select.ext_cs<=0;bitCounter<=0;// clear the counterintState<=8'h03;// jump to the next stateend8'h03:begin// put the MSB onto the busext_sdo<=wordStorage; // make the serial-data-output bit equal to the MSB of the word-storage regintState<=8'h04;end8'h04:beginext_clk<=1;intState<=8'h05;outWord<=ext_sdi;end8'h05:beginext_clk<=0;wordStorage<=wordStorage<<1; // shift all the bits in wordStorage left 1.outWord<=outWord<<1; // shift all the bits in OutWord left 1intState<=8'h06;end8'h06:begin // determine how many bits are left to count...if(23==bitCounter)// we're good.intState<=8'h07;// still shifting.bitCounter<=bitCounter+1;intState<=8'h03;end8'h07:begin// do some cleanup.ext_cs<=1; // indicate we're finished to the device.intState<=8'h08;end8'h08:beginrdy<=1;// indicate we're done with the transaction.intState<=8'h0F;end8'h09: if(1==clr)beginrdy<=0;intState<=8'h01;endendcaseendmodule

author: Muxr
author_rank: Super Contributor
timestamp: June 02, 2015, 05:39:31 am
content: The first step would be to validate your case and why your state counter isn't being incremented. I would recommend using the `case default` block for non matched cases, you can use it instead of your 8'h00 case.I am sorta new to Verilog as well, but one suggestion from reading other people's code, instead of the else block, I would just start a new `always @(posedge clk) if(rst != 1)..` for your state machine.The other issue you might be having is the clock. Perhaps add another counter that's always incrementing in its own always block as a test.I've been using the Lattice's MachX02 and I have to initialize its internal clock like this. (not sure if it matters in a synth tool). I've only used it briefly, I tend to just push the code to the dev board, since I can't be bothered writing test harnesses.Code://// Internal Oscillatordefparam OSCH_inst.NOM_FREQ = "133.00";OSCH OSCH_inst(.STDBY(1'b0),// 0=Enabled, 1=Disabled also Disabled with Bandgap=OFF.OSC(osc_clk),.SEDSTDBY()// this signal is not required if not using SED);//// counter with no flag controlalways @ (posedge osc_clk)Here is a full example:https://eewiki.net/display/LOGIC/Lattice+Diamond+and+MachXO2+Breakout+Board+Tutorial+%28with+Verilog%29

author: 6thimage
author_rank: Regular Contributor
timestamp: June 02, 2015, 04:08:34 pm
content: First of all, have you run this in a simulator at all? The problem should be very obvious when you have the waveforms in front of you.The issue you are having is due to:Code:8'h06:begin // determine how many bits are left to count...if(23==bitCounter)// we're good.intState<=8'h07;// still shifting.bitCounter<=bitCounter+1;intState<=8'h03;endThe setting of intState to 3 is overriding the end condition - you either need an else statement or to move the if statement.The important thing to remember is that the synthesiser converts your code, optimises it and then reports the errors. So the errors it gives will most likely be cryptic - the best I've seen is when xilinx's synthesiser reports that states are unreachable (which it would do in this case), then reports about unused register bits. I'm not sure if Altera's or Lattice's synthesisers report the same thing.You have also written the logic in quite a fast way (large number of states with little logic in each), but you won't get a 50% duty cycle (you'll have 25% high, 75% low), which might cause issues with some SPI devices. I wrote a SPI master a couple of years ago, which I'veattached(in code block below) in case you want to have a look. It's a little over-complicated in places, but is designed to give a square sclk.Code:module spi_master(/* clock */input clk,/* external connections */output reg sclk, /* serial clock */output reg mosi, /* master out, slave in */input miso, /* master in, slave out *//* internal connections */input reset, /* reset - active low */input enable, /* enable / start - starts a spi transaction - active high */input [7:0] clock_div, /* clock divider - spi clock has a maximum of clk/2, this isto reduce it futher */input cpol, /* sclk polarity - 0 for start low, 1 for start high */input cpha, /* sclk phase - if 0, the first bit is transmitted with thefalling edge of sclk, if 1 the first bit isdelayed to the first sclk */input [7:0] tx_data, /* data to transmit */output reg [7:0] rx_data, /* received data - updated when not busy */output reg busy /* busy flag - is 1 during a transaction, 0 otherwise */);initialbeginbusy=1'b0;sclk=1'b1;mosi=1'b1;end/* internal data buffers */reg [7:0] tx_data_int;reg [7:0] rx_data_int=8'hff;/* internal config buffers */reg [7:0] clock_div_int;reg cpol_int, cpha_int;wire cpol_eq_cpha;assign cpol_eq_cpha=(cpol_int==cpha_int);/* serial clock - for dividing the main clock down */reg [7:0] clock_counter;wire clock_counter_hit;assign clock_counter_hit=(clock_counter==clock_div_int);/* bit counter */reg [3:0] bit_counter; /* number of bits sent *//* clock edgessclk state edgeread write read writecpha=0cpol=0 0 1 rising fallingcpol=1 1 0 falling risingcpha=1cpol=0 1 0 falling risingcpol=1 0 1 rising fallingas far as clock edges are concerned, there are two situationsthat determine which edge is used for reading and writingcpol==cphacpol!=cpha*/wire sclk_receive_edge, sclk_transmit_edge;assign sclk_receive_edge=(cpol_eq_cpha)?(sclk==1'b0):(sclk==1'b1);assign sclk_transmit_edge=(cpol_eq_cpha)?(sclk==1'b1):(sclk==1'b0);always @(posedge clk or negedge reset)beginif(!reset)begin/* reset to defaults */busy <= 1'b0;sclk <= 1'b1;mosi <= 1'b1;rx_data_int <= 8'hff;endelsebegin/* detect start */if(enable && !busy)begin/* reset counters */clock_counter <= 8'h0;/* set bit counter to 0 */bit_counter <= 4'h0;/* update config */clock_div_int <= clock_div;cpol_int <= cpol;cpha_int <= cpha;/* start transaction */busy <= 1'b1;sclk <= cpol;/* send first bit if cpha=0 */mosi <= tx_data;if(!cpha)begin/* shift tx data accordingly */tx_data_int <= {tx_data[6:0],1'b0};endelsetx_data_int <= tx_data;end/* manage data transaction */else if(busy)beginif(clock_counter_hit)begin/* reset counter */clock_counter <= 8'h0;/* update clock */if(bit_counter!=4'h8)sclk <= ~sclk; /* toggle clock *//* update bit counter */if(sclk!=cpol_int)bit_counter <= bit_counter+1'b1;if(bit_counter!=4'h8)beginif(sclk_transmit_edge){mosi, tx_data_int} <= {tx_data_int, tx_data_int};else if(sclk_receive_edge)rx_data_int <= {rx_data_int[6:0], miso};endelsebegin/* disable transmission */busy <= 1'b0;/* output received data */rx_data <= rx_data_int;endendelse/* increment counter */clock_counter <= clock_counter+1'b1;endendendendmodule

author: XFDDesign
author_rank: Frequent Contributor
timestamp: June 02, 2015, 05:54:51 pm
content: Aha! Many thanks!I'm working out the simulator issue right now (that is, getting one I can use).With respect to the duty cycle, at the moment I'm not particularly concerned - it was "test an idea and see if it will compile." I'll make the fixes when I get home!

author: XFDDesign
author_rank: Frequent Contributor
timestamp: June 03, 2015, 12:25:01 am
content: As a dumb update, that fixed that set of errors. I got setup with IcarusVerilog and have written some test benches. Now, though, it's bellyaching about the MSB of a register being stuck at zero, so I'm looking at everything which drives that bit. iVerilog, however, has no problems at all and produces expected results.Edit 3/6/2015: I changed the "reset" values to make the "stuck at zero" registers all 1s, and the synthesizer stopped its bellyaching.