Trouble simulating altera-generated floating point units
It is my first time using verilator. I wrote a simple program to test the floating point units generated by altera's tool. Add and multiply work great, but the divide circuit produces the wrong result. I believe it's related to memory, as the divider circuit uses them as look up tables.
I've attached a small demo folder to show the problem. It creates an adder, multiplier, and divider, gives them all the same static inputs, and then sims for 50 clocks to get the answer.
Input: 3.5 and 2.0
When I run the simulation, I get:
Add: 5.500000 Mult: 7.000000 Div: 1.000000
The first two being correct, the divider being wrong (correct is 1.75). When I run the simulation with altera-modelsim, I get the correct answer.
What is wrong here? I did have to use -Wno-fatal as it generates a ton of warnings. However, many of the warnings I investigated proved to be innocuous (and in fact part of altera's libs - quartus prints them as well during synthesis!). Perhaps someone more familiar with Verilator could provide some insight here. I used the scripts from https://github.com/twosigma/verilator_support to convert the altera libraries.
divider_problem.zip (486 KB)
Glad you're giving Verilator a try. It's most likely something simple, perhaps with a hint buried in a warning as you suggest.
I would suggest making a waves dump under both simulators and tracing forwards the major signals until you see a difference and the culprit signal. If the problem still isn't evident a small (~~100 line) failing test is closer to the size that I would be able to find the time to debug.
Ok, I have figured out the issue, but I am unsure how to solve it. Inside the altera memory sim libraries, there is code like this:
reg x; initial begin x = 0; end always @ (posedge clk) begin x <= ~x; end always @ (x) begin // do things end
In modelsim, the code in the always
(x) block is triggered once at the start, and then on each clock thereafter. In verilator, the (x) block is only triggered once at the start of simulation. In this case, the "do things" included updating the output register of the altera "altsyncram", which caused them to all output only 0 (since that is the correct output on cycle 0 and it never triggers again).
You could try the --x-initial-edge flag. Or, add an initial statement.
Hmm, I don't think it's related to that. I just used 'x' as a variable name in my previous code example. There is already an initial block that sets the variable to 0. Both verilator and modelsim toggle the x variable between 0 and 1, but only modelsim triggers the always @(x) block more than once.
Further, I was playing around with the example, and now verilator errors "%Error: Vcounter.cpp:84: Verilated model didn't DC converge". I renamed the 'x' variable to 'tmp' for clarity, and added a counter.
Modelsim output is:
reg tmp; reg [7:0]counter; initial begin tmp = 0; counter = 0; end always @ (posedge clk) begin $display("tmp: %d", tmp); tmp <= ~tmp; end always @ (tmp) begin $display("count it: %d", counter); counter <= counter + 1; end
# tmp: 0 # count it: 0 # count it: 1 # tmp: 1 # count it: 2 # tmp: 0 # count it: 3 # tmp: 1 ... etc
Is this problem fundamentally due to verilator being a cycle simulator instead of an event simulator? Will it be possible to get verilator to simulate this library or do I need to write my own version?
It's a fundamental problem, try rewriting.