I am providing input to an SPI interface. The input signal is a concatenation of several different signals. What I would like to do in simulation is have continuous concatenation of the different signals into one final string that will be sent to the SPI:
logic [7:0] foo; // Signal 1
logic [7:0] bar; // Signal 2
logic [15:0] combine; // Final signal
assign combine = {foo, bar};
task SendSPI;
begin
foo = 8'hFF;
bar = 8'h00;
SendToSpi(combine); // Want it to send 16'hFF00;
endtask;
The above code compiles and runs on the simulator (Cadence NC sim), but the value of combine is undefined (xxxx). I know I can get around this by having a concatenation task:
task CombineSignal;
begin
combine = {foo, bar};
endtask;
and I would call that task everytime I wanted to concatenate, but having continuous assignment work would be really nice! Does anyone know if continuous assignment is possible in a situation like this?
2 Answers 2
I figured out what was going on. The assign combine statement needs time to pass before it takes a new value.
logic [7:0] foo; // Signal 1
logic [7:0] bar; // Signal 2
logic [15:0] combine; // Final signal
assign combine = {foo, bar};
task SendSPI;
begin
foo = 8'hFF;
bar = 8'h00;
SendToSpi(combine); // combine is undefined.
@(negedge clk); // let some simulator time pass.
SendToSpi(combine); // combine now equals 16'hFF00
endtask;
-
\$\begingroup\$ No, the assign statement doesn't need time to pass, it's your task call that needs time. \$\endgroup\$Alain– Alain2013年11月03日 16:15:47 +00:00Commented Nov 3, 2013 at 16:15
You must understand how Verilog simulators schedule events.
If procedural statements appear in different procedural blocks, there is no guarantee for the order of their execution. For example:
initial
begin
a = 0;
b = 1;
end
always a = b;
always b = a;
The above code can result in both a
and b
being 1's, as well as 0's.
However, procedural statements appearing in the same procedural block are guaranteed to execute sequentially:
initial
begin
a = 0;
b = 1;
end
always
begin
a = b;
b = a;
end
The above code will result in both a
and b
being 1's.
The problem with your initial code is that the concatenation operation is outside of the body of the task, therefore there is no way the scheduler can execute it between the statements in the body of the task (because they are executed sequentially, without outside interruption).
However, once you add a sequential construct (@(negedge clk)
), the simulator advances to the next time slot which allows for the concatenation assignment to be executed.
Although the code you provided works for you, it is very bad practice to write Verilog this way. Why don't do this:
logic [7:0] foo; // Signal 1
logic [7:0] bar; // Signal 2
task SendSPI;
begin
foo = 8'hFF;
bar = 8'h00;
SendToSpi({foo, bar}); // Will send 16'hFF00;
endtask;
wire
orreg
instead oflogic
? \$\endgroup\$