cancel
Showing results for 
Search instead for 
Did you mean: 
Highlighted
Anonymous
Not applicable
10,264 Views

Procedural assignment to a non-register: assign vs always_comb?

Jump to solution

Vivado 2016.3, and SystemVerilog sources.

 

Here's an SRAM controller for this asynchronous SRAM chip (the 10ns version). I'm using write cycle alternative 3 on page 15, which is where -OE is always held low. The procedure is to set up your address, then pull -WE low, wait at least 5 nsec for the chip's outputs to go Hi-Z, then put the data on the bus for at least 6 nsec, and raise -WE to high while removing the data from the bus. The chip's outputs come out of Hi-Z at least 2 nsec after -WE is raised to high.

 

I use the positive edge of a clock (clk) to load the state (cmd), and set a bit (write0_mode) if we're in state WRITE0 (write cycle #0). On the second half of that clock cycle (clk = 0), I place the write data onto the bus (chip_data). At all other times, I set the bus to Z.

 

Here's my module (file mem.sv)

 

import register_types::addr_t;
import mem_types::cmd_t;

module mem(
	input bit clk,
	input cmd_t cmd,
	input addr_t addr,
	input byte unsigned write_data,
	output byte unsigned read_data,

    // SRAM chip connections
	output addr_t chip_addr,
	inout logic[7:0] chip_data, // requires z-states
	output bit not_ce,
	output bit not_oe,
	output bit not_we
);

bit write0_mode;
// output for chip_data
always_comb chip_data = (write0_mode && !clk) ? write_data : 'z;

always_comb begin
	read_data = chip_data;
	chip_addr = addr;
	not_oe = 0;
	not_ce = 0;
	not_we = !write0_mode;
end //always_comb

always_ff @(posedge clk) begin
    write0_mode <= cmd == mem_types::WRITE0;
end

endmodule // mem

Vivado gives an error on the always_comb chip_data line:

 

[Synth 8-2576] procedural assignment to a non-register chip_data is not permitted ["F:/plugh1/mem.sv":21]

This makes no sense to me. Because if I replace always_comb with assign, Vivado is happy:

 

assign chip_data = (write0_mode && !clk) ? write_data : 'z;

 

Why would the error happen with always_comb but not with assign?

 

0 Kudos
1 Solution

Accepted Solutions
Highlighted
Scholar
Scholar
15,842 Views
Registered: ‎09-16-2009

Re: Procedural assignment to a non-register: assign vs always_comb?

Jump to solution

 

Your trouble is related to the inout port "chip_data".

 

In Verilog-1995 the rules were a bit simpler - an inout port MUST be declared as a net data type.  So in Verilog-1995 you'd be forced to declare chip_data as:

 

output wire [ 7 : 0 ] chip_data 

Since it was a wire, you could ONLY drive it with an assign, you're done.

 

Now SystemVerilog has type 'logic' (actually "reg" in SystemVerilog allows this now too, but lets not confuse things). The "logic" types have a fuzzy definition - in that they're NOT fully typed in the deceleration.  The tool doesn't know if it's a net type, or variable type until it sees how that variable is used.  If it's driven with an assign, it's a net-type.  If it's driven procedurally, it's variable type.  (Yes, I can hear you VHDL folks sighing).

 

INOUTs cannot be variable type.  So when you drive "chip_data" with a procedural block, the tool correctly gives you the error.

 

Regards,

 

Mark

 

View solution in original post

0 Kudos
4 Replies
Highlighted
Scholar
Scholar
15,843 Views
Registered: ‎09-16-2009

Re: Procedural assignment to a non-register: assign vs always_comb?

Jump to solution

 

Your trouble is related to the inout port "chip_data".

 

In Verilog-1995 the rules were a bit simpler - an inout port MUST be declared as a net data type.  So in Verilog-1995 you'd be forced to declare chip_data as:

 

output wire [ 7 : 0 ] chip_data 

Since it was a wire, you could ONLY drive it with an assign, you're done.

 

Now SystemVerilog has type 'logic' (actually "reg" in SystemVerilog allows this now too, but lets not confuse things). The "logic" types have a fuzzy definition - in that they're NOT fully typed in the deceleration.  The tool doesn't know if it's a net type, or variable type until it sees how that variable is used.  If it's driven with an assign, it's a net-type.  If it's driven procedurally, it's variable type.  (Yes, I can hear you VHDL folks sighing).

 

INOUTs cannot be variable type.  So when you drive "chip_data" with a procedural block, the tool correctly gives you the error.

 

Regards,

 

Mark

 

View solution in original post

0 Kudos
Highlighted
Anonymous
Not applicable
10,211 Views

Re: Procedural assignment to a non-register: assign vs always_comb?

Jump to solution

Ahhhh, I see. OK, that was a whole other dimension to port declarations that I didn't know about. In the 2012 standard you can specify the type (wire or var) or a port, so if I had tried to specify the port as var and not just leave it up to the compiler, I would have gotten this error:

 

[Synth 8-3966] non-net port chip_data cannot be of mode inout: `default_nettype is "none" ["F:/plugh1/mem.sv":13]

That would have given me a much better clue :)

 

0 Kudos
Highlighted
Scholar
Scholar
10,155 Views
Registered: ‎09-16-2009

Re: Procedural assignment to a non-register: assign vs always_comb?

Jump to solution

 

To be honest, I don't know just WHAT the 'var' keyword does.  It was added within the SystemVerilog spec, but to me, it's purpose is entirely unclear.  I've read that section of the specification multiple times, and as yet can't decipher what the keyword 'var' actual does, or what it's trying to solve.

 

To be clear, I've never used it, and never really seen it used.

 

There used to be an archive available of the SystemVerilog working group's messages.  It was veryhelpful to peruse - one could get a sense of how and why the language was developed in the way it was.  Unfortunately, the archive all but vanished.  Using the Wayback machine, I can find a few threads, but nothing representing the whole archive. 

 

Maybe another SystemVerilog expert can chime in on just what 'var' does...

 

Regards,

 

Mark

0 Kudos
Highlighted
Guide
Guide
10,145 Views
Registered: ‎01-23-2009

Re: Procedural assignment to a non-register: assign vs always_comb?

Jump to solution

If it's driven with an assign, it's a net-type.  If it's driven procedurally, it's variable type.

 

This isn't technically true (although it is close enough for most stuff)

 

Officially, a "logic" is a kind of "variable" type (as opposed to wire, which is of "net" type).

 

In Verilog:

  Nets are driven by any number of continuous assigns or ports

    - conflict resolution determines the final value if multiple drivers exists

  Variables are driven by procedural assignments

 

In SystemVerilog:

  Nets are driven by any number of continuous assigns or ports

    - conflict resolution determines the final value if multiple drivers exists

  Variables are driven by procedural assignments or a single continuous assign or port (not both)

    - since there is only one continuous assign/port, there is no conflict resolution  

 

(See section 6.5 of IEEE_1800-2012)

 

Avrum

0 Kudos