aboutsummaryrefslogtreecommitdiffstats
path: root/example
diff options
context:
space:
mode:
authorYann Herklotz <git@yannherklotz.com>2020-10-15 09:25:52 +0100
committerYann Herklotz <git@yannherklotz.com>2020-10-15 09:25:52 +0100
commit6c9cc975a5715f186c00e487c4ed38a221711651 (patch)
treea1255876fd7acc6faededaf18e87c14ec207fec6 /example
parented8336189707bd1575de3cfffa730a2594086a33 (diff)
downloadvericert-6c9cc975a5715f186c00e487c4ed38a221711651.tar.gz
vericert-6c9cc975a5715f186c00e487c4ed38a221711651.zip
Add HTLBlockgen and more scheduling
Diffstat (limited to 'example')
-rw-r--r--example/explanation.org81
-rw-r--r--example/interesting.v36
2 files changed, 117 insertions, 0 deletions
diff --git a/example/explanation.org b/example/explanation.org
new file mode 100644
index 0000000..793c890
--- /dev/null
+++ b/example/explanation.org
@@ -0,0 +1,81 @@
+#+title: Interesting edge case in Simulation and Synthesis Mismatch
+
+I have always known about situations where the simulation might not match the synthesised result, for example when blocking assignment is used in one always block and is read from another. However, the following mismatch is slightly surprising to me because I feel like simulators should be giving the same result as synthesis tools, as it seems to be quite common. Otherwise, it also seems fair that the synthesis tool should implement what the simulator is showing, as it is strange to get such different results.
+
+I tested the following with the Quartus 20.1 and Yosys 0.9+2406 synthesis tool (which both gave the same result) and the icarus verilog, verilator and ModelSim simulators which also agreed with each other.
+
+Assuming we want to implement the following design. My expectation would be that it just basically assigns ~a~ to ~x~ whenever ~a~ changes.
+
+#+begin_src verilog
+module top(a, x);
+ reg [3:0] tmp;
+ input [3:0] a;
+ output reg [3:0] x;
+
+ always @* begin
+ x = tmp;
+ tmp = a;
+ end
+endmodule // top
+#+end_src
+
+This seems to be correct when looking at the synthesised design printed by Yosys.
+
+#+begin_src verilog
+/* Generated by Yosys 0.9+2406 (git sha1 000fd08198, clang++ 7.1.0 -fPIC -Os) */
+module top_synth(a, x);
+ input [3:0] a;
+ wire [3:0] tmp;
+ output [3:0] x;
+ assign tmp = a;
+ assign x = a;
+endmodule
+#+end_src
+
+However, when simulating it with the following testbench, it instead acts like a shift register.
+
+#+begin_src verilog
+module main;
+ reg [3:0] a;
+ wire [3:0] x, x_synth;
+
+ top top(a, x);
+ top_synth top_synth(a, x_synth);
+
+ initial begin
+ a = 0;
+ #10 a = 1;
+ #10 $display("x: %d\nx_synth: %d", x, x_synth);
+ $finish;
+ end
+endmodule
+#+end_src
+
+The test bench above prints
+
+#+begin_src text
+x: 0
+x_synth: 1
+#+end_src
+
+showing that the synthesised design does not match the simulated design.
+
+Is the test bench that I wrote slightly broken? Or is this expected to be this different. In the latter case, how come simulators don't implement the correct behaviour? This could be done by recursing and reevaluating the always block when an element in the sensitivity list changed, even if that was in the same always block.
+
+Even in simulation I would expect these two snippets to act the same
+
+#+begin_src verilog
+always @* begin
+ x = tmp;
+ tmp = a;
+end
+#+end_src
+
+#+begin_src verilog
+always @* begin
+ tmp = a;
+ x = tmp;
+end
+#+end_src
+
+Because ~a~ and ~tmp~ are both in the sensitivity list, meaning in the first code snippet, it should reevaluate the always block and update the ~x~ register with the correct value which is ~a~.
diff --git a/example/interesting.v b/example/interesting.v
new file mode 100644
index 0000000..c76f92a
--- /dev/null
+++ b/example/interesting.v
@@ -0,0 +1,36 @@
+module top(a, x);
+ reg [3:0] tmp;
+ input [3:0] a;
+ output reg [3:0] x;
+
+ always @* begin
+ x = tmp;
+ tmp = a;
+ end
+endmodule // top
+
+`ifndef SYNTHESIS
+/* Generated by Yosys 0.9+2406 (git sha1 000fd08198, clang++ 7.1.0 -fPIC -Os) */
+module top_synth(a, x);
+ input [3:0] a;
+ wire [3:0] tmp;
+ output [3:0] x;
+ assign tmp = a;
+ assign x = a;
+endmodule
+
+module main;
+ reg [3:0] a;
+ wire [3:0] x, x_synth;
+
+ top top(a, x);
+ top_synth top_synth(a, x_synth);
+
+ initial begin
+ a = 0;
+ #10 a = 1;
+ #10 $display("x: %d\nx_synth: %d", x, x_synth);
+ $finish;
+ end
+endmodule
+`endif