Open rohitk-singh opened 6 years ago
Yes it's a bug; can you patch it, test it carefully, and send a PR?
Sure, let me give it a try.
@sbourdeauducq, @jordens and @whitequark: Could you please review this commit: https://github.com/rohitk-singh/migen/commit/b3206e2b6bf179469f55fabf41bb2f6cea3a617e
It seems to solve the above issue.
If the way to solve it is to allow special outputs to be reg
, then the comb
assign in MultiRegImpl
and maybe other places (please check) becomes unnecessary.
sort-of related question: in general, it is considered "good verilog" to use only blocking assignments in combinational (e.g., "always @(*)" blocks, and I noticed that migen uses nonblocking "<=" throughout all such blocks. I wonder if simply generating "="s instead of "<="s for combinational (note: NOT synchronous) blocks wouldn't be a better fix? EDIT: nevermind, I notice this is already being discussed in a few other migen PRs; sorry for the noise :)
Triage: fixed in nMigen.
I wrote a Migen code which used MultiReg for signal synchronization across clock domains and the relevant section is similar to the test code below:
The verilog output of this code is:
Incorrect Code Section ```verilog wire [1:0] done; always @(*) begin done <= 2'd0; done[0] <= multiregimpl01; done[1] <= multiregimpl11; end ```
Complete generated verilog file (cleaned up) : ```verilog module top( input rx_clk, input rx_rst, input sys_clk, input sys_rst ); reg [7:0] counter = 8'd0; wire [1:0] done; (* no_retiming = "true" *) reg multiregimpl00 = 1'd0; (* no_retiming = "true" *) reg multiregimpl01 = 1'd0; (* no_retiming = "true" *) reg multiregimpl10 = 1'd0; (* no_retiming = "true" *) reg multiregimpl11 = 1'd0; always @(*) begin done <= 2'd0; done[0] <= multiregimpl01; done[1] <= multiregimpl11; end always @(posedge rx_clk) begin counter <= (counter + 1'd1); if (rx_rst) begin counter <= 8'd0; end end always @(posedge sys_clk) begin multiregimpl00 <= counter[0]; multiregimpl01 <= multiregimpl00; multiregimpl10 <= counter[1]; multiregimpl11 <= multiregimpl10; end endmodule ```Issue
The problem with above generated verilog is that
done[1:0]
is declared aswire
instead of being declared asreg
since it is being assigned inside thealways
block.It might be fault of the coding style used in the above test code, but creating object with Test(1) instead of Test(2) gives correct output: https://hastebin.com/jiwomizawe.scala
Also, if I refactor the code to this:
then I get correct verilog output -> https://hastebin.com/bujarijeqe.scala
I can definitely use the refactored code to get intended output but just wanted to confirm whether this is a bug or not.