Is this allowed?
input w;
input [8:0]y;
output reg [8:0]x;
always@(w)
begin
//x[0] or A is never on in any next state
assign x[0] = 0;
assign x[1]= (y[0]&~w) | (y[5]&~w) | (y[6]&~w) | (y[7]&~w) | (y[8]&~w); //B
assign x[2]= (y[1]&~w); //C
assign x[3]= (y[2]&~w); //D
assign x[4]= (y[3]&~w) | (y[4]&~w); //E
assign x[5]= (y[0]&w) | (y[1]&w) | (y[2]&w) | (y[3]&w) | (y[4]&w); //F
assign x[6]= (y[5]&w);
assign x[7]= (y[6]&w);
assign x[8]= (y[7]&w) | (y[8]&w);
end
You can, it's called a "Procedural Continuous Assignment". It overrides ordinary procedural assignments, there doesn't seem to be a call for them in the code you've posted. I'm not sure if they're synthesisable, but I never have cause to use them anyway.
A note on your code - you're missing y
from your sensitivity list: eg always @( w or y )
or always @(*)
is safer.
Building upon Marty's answer, you should read section 9.3 of the IEEE Verilog Standard (1364-2005, for example), where it describes "Procedural Continuous Assignment". The spec allows for assign
statements within an always
block. However, from my experience, it is quite rare.
Another issue with your code is that it has compile errors with two different simulators that I tried. Both generate error messages that bit-selects or part-selects cannot be used on the left hand side of the assignment.
Another possible solution is to get rid of the always
block, and just use simple continuous assignments.
input w;
input [8:0] y;
output [8:0] x;
assign x[0] = 0;
assign x[1]= (y[0]&~w) | (y[5]&~w) | (y[6]&~w) | (y[7]&~w) | (y[8]&~w); //B
assign x[2]= (y[1]&~w); //C
assign x[3]= (y[2]&~w); //D
assign x[4]= (y[3]&~w) | (y[4]&~w); //E
assign x[5]= (y[0]&w) | (y[1]&w) | (y[2]&w) | (y[3]&w) | (y[4]&w); //F
assign x[6]= (y[5]&w);
assign x[7]= (y[6]&w);
assign x[8]= (y[7]&w) | (y[8]&w);
Assign is a continuous assignment statement which is used with wires in Verilog. assign statements don't go inside procedural blocks such as always. Registers can be given values in an always block.
Assign statements can be viewed as:
always @(*)
statements for wires.
The procedural continuous assign
statement was intended to be an optimized way of writing a mux-like behavior. For example, if you have
always @(A or B or select)
if (select)
out = A;
else
out = B;
You could write this as
always @(select)
assign out = A;
else
assign out = B;
But people don't like having to deal with sensitivity lists, so @(*)
was added to Verilog, and SystemVerilog added always_comb
.
But the real killer for this construct is that many people would write code like
always @(*)
assign out = A;
Which simulates fine, but you now have a double penalty in performance because the assign
statement is already sensitive to changes in A, but so is the always
block. This repeatedly executes the procedural assign
statement replacing the same RHS.
Yes, but you don't want to. Since x[] doesn't depend on x[] the order doesn't matter. Just use <= instead of assign =.
There is no need using assign inside a procedural block (In this case Always)
Assign is a continuous assignment, and it has to go outside a procedural block.