I'm teaching myself Verilog with HDLbits and tackling this problem. According to this post, assignment with the LHS of the expression as a concatenation should work. In practice I've used this many times before. However, when I assign a wire to a concatenation and then use a non-blocking assignment on that wire, the wire is not driven.
module top_module (
input clk,
input reset,
input [3:1] s,
output fr3,
output fr2,
output fr1,
output dfr
);
parameter lowest = 3'b000, aboveS1 = 3'b001, aboveS2 = 3'b011, aboveS3 = 3'b111;
parameter hf = 3'b111, mf = 3'b011, lf = 3'b001, zf = 3'b000;
reg [2:0] state, next_state;
wire [2:0] flowrate = {fr3,fr2,fr1}; //problem area
always @ * begin
next_state = {s[3],s[2],s[1]};
end
always @ (posedge clk) begin
if(reset) begin
state <= lowest;
{fr3,fr2,fr1} <= hf;
dfr <= 1'b1;
end else begin
if(next_state != state)
dfr <= next_state < state;
else
dfr <= dfr;
case(next_state)
aboveS1 : flowrate <= mf; //problem area
aboveS2 : flowrate <= lf;
aboveS3 : flowrate <= zf;
default : flowrate <= hf;
endcase
state <= next_state;
end
end
endmodule
The above code fails as fr3, fr2, and fr1 are stuck at ground. But when the case statement is changed to the following:
aboveS1 : {fr3,fr2,fr1} <= mf;
aboveS2 : {fr3,fr2,fr1} <= lf;
aboveS3 : {fr3,fr2,fr1} <= zf;
default : {fr3,fr2,fr1} <= hf;
The code works fine, and the outputs are driven. Why does this occur?
There is also this warning thrown by Quartus which I'm sure is related:
Warning (10036): Verilog HDL or VHDL warning at top_module.v(13):
object "flowrate" assigned a value but never read File:
/home/h/work/hdlbits.2001977/top_module.v Line: 13
Warning (13024): Output pins are stuck at VCC or GND
Warning (13410): Pin "fr3" is stuck at VCC File:
/home/h/work/hdlbits.2001977/top_module.v Line: 5
Warning (13410): Pin "fr2" is stuck at VCC File:
/home/h/work/hdlbits.2001977/top_module.v Line: 6
Warning (13410): Pin "fr1" is stuck at VCC File:
/home/h/work/hdlbits.2001977/top_module.v Line: 7
The following replacements in the upper area also break:
wire [2:0] flowrate;
assign {fr3,fr2,fr1} = flowrate;
and
wire [2:0] flowrate;
assign flowrate = {fr3,fr2,fr1};
Edit: clarified error a bit more
2 Answers 2
Two main issues:
- Assignments are make to the LHS (Left-Hand-Side).
- Anything assigned by an always block needs to be a non-net type.
flowrate
should be areg
type instead of awire
.
Therefore:
wire [2:0] flowrate = {fr3,fr2,fr1};
Should be:
reg [2:0] flowrate;
assign {fr3,fr2,fr1} = flowrate;
You seem to be expecting that the declaration
wire [2:0] flowrate = {fr3,fr2,fr1};
creates some sort of bidirectional equivalence between flowrate
and the three outputs, such that assigning to flowrate
is in effect an assignment to the outputs. There's nothing about the semantics of the Verilog language that would support this.
Instead, you would need to do something more like:
wire [2:0] flowrate;
assign {fr3,fr2,fr1} = flowrate;
-
\$\begingroup\$ Well, that breaks because there are multiple drivers for flowrate then, in the sequential logic and the assign statement \$\endgroup\$Michael– Michael2021年10月01日 05:05:19 +00:00Commented Oct 1, 2021 at 5:05
-
\$\begingroup\$ Thanks for your help, I should've noted that I originally wrote and tested it with assign statements outside of the declaration, I must've accidentally changed that line when I was editing it to post on SO. \$\endgroup\$Michael– Michael2021年10月01日 05:17:13 +00:00Commented Oct 1, 2021 at 5:17
alias
andlet
constructs that both give you the bidirectional semantics you are looking for. \$\endgroup\$