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.

\$\endgroup\$
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.

\$\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\$
    – user105652
    Aug 11 '20 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\$
    – jonk
    Aug 11 '20 at 1:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.