steveicarus / iverilog

Icarus Verilog
https://steveicarus.github.io/iverilog/
GNU General Public License v2.0
2.86k stars 530 forks source link

I think a signal goes up one clock cycle too early #1114

Closed spth closed 6 months ago

spth commented 7 months ago

In the current release (12.0 via the Debian package) I noticed a difference in pre- and post-synthesis simulation in my code. After looking into it, I think the pre-synthesis simulation is wrong.

The affected Verilog file is this:

`begin_keywords "1800-2009"

// Interrupt controller for up to 16 interrupt input lines and one interrupt output line
// I/O registers: enable (up to 16 bit), active (up to 16 bit)
module interruptcontroller #(parameter NUM_INPUTS = 1) (output logic int_out, output logic [NUM_INPUTS-1:0] enable_out, active_out, input logic [NUM_INPUTS-1:0] enable_in, active_in, input logic enable_in_write, active_in_write, input logic [NUM_INPUTS-1:0] in, input logic clk, input logic reset);
    logic [NUM_INPUTS-1:0] enablereg, activereg;

    always @(posedge clk)
    begin
        if (reset)
        begin
            enablereg = 0;
            activereg = 0;
        end
        else
        begin
            if (enable_in_write)
                enablereg = enable_in;
            if (active_in_write)
                activereg = active_in;
            activereg |= in & enablereg;
        end
    end
    assign int_out = |activereg;
    assign enable_out = enablereg;
    assign active_out = activereg;

endmodule

`end_keywords

Apparently, the lowest bit of activereg goes up the moment the lowest bit of in goes up when the lowest bit of enablereg is 1, but I think that should happen at the next rising clock edge:

gtkwave

My full source is at https://sourceforge.net/p/sdcc/code/14785/tree/branches/f8/f8/hardware/, but I've also attached what I think are the relevant files for this issue.

test.vmem.gz test2.vcd.gz alu2.v.gz cpu2.v.gz gpio.v.gz interruptcontroller.v.gz io2.v.gz memory2.v.gz opcode.v.gz ram2.v.gz rom2.v.gz system2.v.gz testsystem2.v.gz timer.v.gz watchdog2.v.gz

martinwhitaker commented 7 months ago

At a quick glance, this is most likely because you have used blocking assignments to model sequential logic. Try changing them to nonblocking assignments.

I recommend reading http://www.sunburst-design.com/papers/CummingsSNUG2000SJ_NBA.pdf

caryr commented 6 months ago

Did updating this to use blocking assignments for the sequential elements resolve the issue?

martinwhitaker commented 6 months ago

No response, so closing.