2
\$\begingroup\$

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?

asked Sep 23, 2013 at 18:45
\$\endgroup\$
2
  • \$\begingroup\$ Does combine[15:8] = foo; combine[7:0] = bar; work? \$\endgroup\$ Commented Sep 23, 2013 at 18:50
  • \$\begingroup\$ Have you tried declaring the variable type as wire or reg instead of logic? \$\endgroup\$ Commented Sep 23, 2013 at 18:58

2 Answers 2

3
\$\begingroup\$

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;
answered Sep 23, 2013 at 23:08
\$\endgroup\$
1
  • \$\begingroup\$ No, the assign statement doesn't need time to pass, it's your task call that needs time. \$\endgroup\$ Commented Nov 3, 2013 at 16:15
1
\$\begingroup\$

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;
answered Sep 24, 2013 at 20:27
\$\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.