0
\$\begingroup\$

I am making a parallel-to-serial shift register and I got it to load correctly, but with only with an extra clock cycle/ extra byte. I am wondering what the difference is between two snippets that look almost the same.

This Verilog works:

//Parallel-in serial-out shift register 
reg [15:0]temp = 16'habcd;
always @ (posedge clk) begin
 if(load) begin
 temp <= din;
 end
 else begin
 temp <= {temp[14:0], 1'b1};
 end
end
assign dout = temp[15];

Microcontroller Output (correct):

00 00 ff ff ff ff ff ff

This Verilog does not work:

//Parallel-in serial-out shift register 
reg [15:0]temp = 16'habcd;
always @ (posedge clk) begin
 temp <= {temp[14:0], 1'b1};
end
always @ (posedge load) begin
 temp <= din;
end
assign dout = temp[15];

Microcontroller output (wrong):

00 00 00 00 00 00 00 00

Microcontroller code for both Verilog snippets:

function read8bytes() {
 spi_latch_pin.write(1);
 /* dummy first byte used only to latch the counter data */
 spi.readblob(1);
 
 spi_latch_pin.write(0);
 /* actual counter data */ 
 local s = spi.readblob(8);
 // ...and return it
 return s;
} 
// Log results from the above functions
server.log(read8bytes().tostring());

I believe the answer is that there is a race condition in the code where the register "temp" can be edited in two "always" blocks simultaneously. I found that the Verilog doesn't build when I reverse the order of the "always" blocks either with the error "'temp' has multiple output drivers" So I'm going to keep the dummy byte. I just thought the Verilog would work despite the race condition.

asked Aug 11, 2020 at 0:08
\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

The Verilog that does not work is having trouble because you're trying to edge-trigger a register with two different clocks. That's Simply Not Done -- I suspect that the Verilog spec says that the simulator can do whatever it wants with that (because -- don't do that).

The Verilog that does work is done properly, as best as I can tell. I'm not sure why you think there's "an extra byte", unless you're a bit confused about the fact that the load is synchronous, which means that the load needs to be active when the clock goes high. Looking at the waveforms for load and clock may illuminate what's going on there.

answered Aug 11, 2020 at 1:37
\$\endgroup\$
2
  • \$\begingroup\$ Agreed. "Always" cannot repeat as it creates 2 triggers. Also the "if" statement forces the code to check trigger condition before proceeding. \$\endgroup\$ Commented Aug 11, 2020 at 1:43
  • \$\begingroup\$ Also, in the case that doesn't work I believe Verilog doesn't specify which of the two always blocks has "priority." They operate in parallel so either may occur independent of the other. (This may be a case where blocking = and non-blocking <= doesn't matter since both blocks are independent and neither block has more than one such line.) But perhaps it's been too many years for me. So am I getting that wrong? \$\endgroup\$ Commented Aug 11, 2020 at 1:44

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.