2
\$\begingroup\$

I get a bunch of these errors on the following code:

(VERI-1100) procedural assignment to a non-register 'nextstate' is not permitted

The problem is mostly with the case statement.

I am genuinely confused. My design clearly cannot be implemented using clocked registers for these signals. I've tried several versions, with assign, with and without always and can't get it to compile.


// SPI Master in Mode 3
module SPIMode3(
 //external PHY interface
 cs,
 sclk,
 misoA,
 misoB,
 mosi,
 //internal interface
 spiclk,
 en,
 busy,
 misoA_pbus,
 misoB_pbus,
 mosi_pbus
 );
 
 //PARAMS
 parameter SPI_BITS = 16;
 parameter STATE_DONE = 2'd0;
 parameter STATE_RUNNING = 2'd1;
 
 //PORTS
 //external PHY
 output cs;
 output sclk;
 input misoA;
 input misoB;
 output mosi;
 //internal interface
 input spiclk; //would like for spiclk=sclk directly
 input en; //module is active when HIGH, rising edge loads the buffers
 output busy;
 output [(SPI_BITS-1):0] misoA_pbus;
 output [(SPI_BITS-1):0] misoB_pbus;
 input [(SPI_BITS-1):0] mosi_pbus;
 
 //REG/WIRE DECLARATIONS
 reg [1:0] state;
 wire [1:0] nextstate;
 
 reg [7:0] spi_counter;
 wire [7:0] spi_counter_in;
 
 reg [(SPI_BITS-1):0] misoA_reg;
 reg [(SPI_BITS-1):0] misoB_reg;
 reg [(SPI_BITS-1):0] mosi_reg; //technically this is redundant, could use one of the miso reg
 
 wire [(SPI_BITS-1):0] misoA_in;
 wire [(SPI_BITS-1):0] misoB_in;
 wire [(SPI_BITS-1):0] mosi_in;
 
 //REG INPUT ASSIGNMENTS
 always @ * begin
 case (state)
 STATE_DONE: begin
 nextstate = STATE_DONE; // in DONE state, everything just stops
 //REG ASSIGNMENTS
 spi_counter_in = spi_counter;
 misoA_in = misoA_reg;
 misoB_in = misoB_reg;
 mosi_in = mosi_reg;
 //OUTPUT ASSIGNMENTS
 cs = 1;
 sclk = 1;
 mosi = 1;
 busy = 0;
 misoA_pbus = misoA_reg;
 misoB_pbus = misoB_reg;
 end
 
 STATE_RUNNING: begin
 nextstate = (spi_counter < (SPI_BITS-1))? STATE_RUNNING : STATE_DONE;
 //REG ASSIGNMENTS
 spi_counter_in = spi_counter + 1;
 misoA_in = {misoA_reg[(SPI_BITS-2):0], misoA}; //left shifting
 misoB_in = {misoB_reg[(SPI_BITS-2):0], misoB}; //left shifting
 mosi_in = {mosi_reg[(SPI_BITS-2):0], 1'b0}; //left shifting
 //OUTPUT ASSIGNMENTS
 cs = 0;
 sclk = spiclk;
 mosi = mosi_reg[(SPI_BITS-1)]; //MSB out first;
 busy = 1;
 misoA_pbus = misoA_reg;
 misoB_pbus = misoB_reg;
 end
 
 default: begin
 nextstate = STATE_DONE; // in DONE state, everything just stops
 //REG ASSIGNMENTS
 spi_counter_in = spi_counter;
 misoA_in = misoA_reg;
 misoB_in = misoB_reg;
 mosi_in = mosi_reg;
 //OUTPUT ASSIGNMENTS
 cs = 1;
 sclk = 1;
 mosi = 1;
 busy = 0;
 misoA_pbus = misoA_reg;
 misoB_pbus = misoB_reg;
 end
 endcase
 end
 
 always @ (posedge spiclk, negedge en) begin
 if(!en) begin
 state <= STATE_DONE;
 spi_counter <= 0; //will this cause a BUGGGG???
 misoA_reg <= 0;
 misoB_reg <= 0;
 mosi_reg <= 0; //this may be suboptimal
 end
 else begin
 state <= nextstate;
 spi_counter <= spi_counter_in;
 misoA_reg <= misoA_in;
 misoB_reg <= misoB_in;
 mosi_reg <= mosi_in;
 end
 end
endmodule
toolic
10.8k11 gold badges31 silver badges35 bronze badges
asked Mar 28, 2022 at 18:19
\$\endgroup\$

2 Answers 2

2
\$\begingroup\$

You declared nextstate as type wire. It is illegal to make a procedural assignment (within an always block) to a wire. You need to declare the signal as logic:

logic [1:0] nextstate;

Do this for all signals which are assigned in the always block.

You must also do this for the output ports which are assigned in the always block. For example:

output logic cs;

These outputs did not explicitly use wire, but they default to a net type.

Note: You could have used reg instead of logic (since they are synonyms in SystemVerilog), but logic is recommended.

answered Mar 28, 2022 at 18:39
\$\endgroup\$
0
0
\$\begingroup\$

There are many lines in the code where something is declared a wire when it should be a reg. Contrary to their name, regs don't necessarily correspond to physical registers.

See this link
https://blogs.sw.siemens.com/verificationhorizons/2013/05/03/wire-vs-reg/
or just do an internet search on 'Verilog reg'.

SystemVerilog relieves this design choice by allowing the type 'logic' where the tool infers the correct kind (wire or reg). If you are using SystemVerilog, change all your wires and regs to logic, and let the tool do what it knows best.

answered Mar 28, 2022 at 18:41
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.