Giter VIP home page Giter VIP logo

Comments (19)

cliffordwolf avatar cliffordwolf commented on August 17, 2024

[...] and I don't know how to go about debugging it.

You should always simulate your circuits. I have made the necessary changes to your test case (yosys is a bit relaxed with what verilog code it accepts compared to what simulators like Icarus Verilog usually expect) and added a small test bench:

Simulating with this testbench reveals that the circuit does not meet its spec either way:

Because the uart output port valid, stays high, the code

if (uart0_valid && uart0_data_in == "a") begin
    ptr <= 9'h0;
    state <= S_OP;
end

is always active and the FSM is stuck at ptr=0 and state=S_OP.

Please use this patch to build a proper testbench that can be used to validate the circuit behavior in a simulation environment. With a working testbench I can run post-synthesis simulations that allow me to isolate the cause of the diverging post-synthesis circuit behavior.

from yosys.

laanwj avatar laanwj commented on August 17, 2024

Thanks for the patch, I'll try getting the testbench to work first.
Er yes - the UART read should definitely only happen in S_IDLE, and only for one character.

from yosys.

laanwj avatar laanwj commented on August 17, 2024

Ok, updated the repository with the testbench. Both ok and fail produce the same output, and it looks like the correct one (shortened the test pattern to just 'hello\n' or

00010110 10100110 00110110 00110110 11110110 01010000

schermafdruk van 2015-09-07 14 41 05

Waveform files are byte-wise equal.

from yosys.

cliffordwolf avatar cliffordwolf commented on August 17, 2024

Just a short update:

  • I have now reproduced the problem in hardware and will further investigate later today.
  • Is it possible that you forgot to git add testbench.sh and testbench.v?

from yosys.

laanwj avatar laanwj commented on August 17, 2024

Oops - pushed the testbench script and v

from yosys.

cliffordwolf avatar cliffordwolf commented on August 17, 2024

Another update: I have now isolated to problem to be in the resource sharing pass in yosys. I will investigate the issue further over the weekend..

Here is another patch for your experiment, reflecting the current state of my troubleshooting efforts:
http://scratch.clifford.at/laanwj-yosys-ice-experiments-upd2.patch

jfyi: The sed -i 's/WCLKN/WCLK/; ... in the Makefile is a temporary workaround. Working with your code, I have now realized that the iCE40 primitive with negative egde clocks have Ns appended to the negative edge clock inputs. This is now corrected in Yosys and icestorm, but it is not yet corrected in arachne-pnr.

from yosys.

cliffordwolf avatar cliffordwolf commented on August 17, 2024

I have now fixed this issue in commit e7c018e. Thanks for reporting this problem. Please do not hesitate to report bugs in the future. It is very appreciated.

Just for completeness: Here is a patch with my final version of the test bench (replaces the previous upd2): http://scratch.clifford.at/laanwj-yosys-ice-experiments-upd3.patch

from yosys.

laanwj avatar laanwj commented on August 17, 2024

Thanks a lot for tracking the problem down and fixing!

I'll apply your patch and re-test next week. I've been in travel last few days so haven't been able to do much.

from yosys.

laanwj avatar laanwj commented on August 17, 2024

Confirmed fixed.

I did have a bug in my experiment with regard to initialization. What is the recommended way to initialize values in synthesizable logic with this toolchain on ICE FPGAs?

  • Initializer values on registers: this results in "Warning: Wire top._uart0._rx.hh has an unprocessed 'init' attribute." so I suppose not.
  • Explicit reset logic
    • Synchronous/asynchronous preferred?
    • Is it possible to trigger this automatically after the device is flashed or powered on? Currently I make use of an assumption that a register starts out at 0, then trigger reset on the first clock pulse, but if initial state is undefined that's fragile
    • Wire one of the serial control pins to the reset (as in swapforth) - this is good for resetting it later, but doesn't seem to be required initially
  • initial blocks: haven't tried this, I suppose not

I haven't been able to find anything conclusive as it appears to differ per hardware.

from yosys.

cliffordwolf avatar cliffordwolf commented on August 17, 2024

Initializers such as reg foo = 0; and initial blocks both work with yosys (that's why you get the warning in the first place), but the ice40 architecture does not support initialization values for the registers, so whatever initialization value you set is being ignored. But all registers in the iCE40 are set to 0 when the bitstream is fed into the device, so you can ignore the warning for everything that you want to initialize to zero anyways.

You can use explicit reset logic: The tools and the architecture both support synchronous and asynchronous reset. But as a general rule for HDL design I would recommend synchronous reset over asynchronous reset for various reasons.

Yes, you can also use the fact that registers are initialized to zero to generate a reset pulse. I usually do something like the following (only 5 LCs big and generates a 16 cycles long reset pulse):

reg [3:0] reset_cnt = 0;
wire resetn = &reset_cnt;
always @(posedge clk)
  if (!resetn) reset_cnt <= reset_cnt + 1;

from yosys.

laanwj avatar laanwj commented on August 17, 2024

Thanks - so every register does get initialized to 0 - OK I can't explain the issue I had, then.

I thought it had to do with the state being undefined at startup causing the state machine to not work, so I added the state initialization to the reset block (which indeed uses a one-time pulse by a register initialized to 0) and then it worked.

But given that, it shouldn't have an effect, as 0 is the valid reset state.

I'll try if I can reproduce the issue.

from yosys.

cliffordwolf avatar cliffordwolf commented on August 17, 2024

Thanks - so every register does get initialized to 0 - OK I can't explain the issue I had, then.

I have not found anything in the Lattice documentation that indicates that registers are initialized to 0, but I have done a few of tests to verify this and in my tests it was pretty clear that this is what happens.

That being said: In many applications the clock isn't stable when the device is programmed and thus it is possible that the state of the circuit gets corrupted shortly after power on. So you either want to gate the clock and only let it through to your logic once it has been stabilized, or -- especially if you are already using a PLL -- use the LOCK output of the PLL as inverted reset signal for your design.

However, reg foo; and reg foo = 0; do not always yield the same result! If you need the register to be zero initialized, you have to tell the tools! Otherwise the initial value is assumed to be undefined, which allows yosys to perform more optimizations. Two examples:

(1) If you are using retiming in your flow (run synth_ice40 with -retime), then yosys will possibly move any register that does not have an init value assigned. For example, when a register is moved to the other side of an inverter, then the effective initialization value of that register changes from 0 to 1.

(2) Consider the following code for a simple reset generator:

reg resetn = 0;
always @(posedge clk)
  resetn <= 1;

This will work. However, it won't work if you remove the initialization value like this:

reg resetn;
always @(posedge clk)
  resetn <= 1;

According to the language definition, the resetn register now starts out as undefined and can only be set to 1. Thus the tool may remove the register altogether and simply replace resetn with a constant 1.

I can only further underline the importance of simulation, as simulation correctly initializes non-initialized registers with the special undefined x state and lets you see the difference between zero-initialized and uninitialized FFs. If you only test in hardware, you can have situations where (maybe depending on unrelated changes in the design) the synthesis tool sometimes takes an optimization that break the zero-initialized FF assumption and sometime it does not. You'll never find a bug like this in a complex design without a simulation that correctly models the x state.

from yosys.

cseed avatar cseed commented on August 17, 2024

I have not found anything in the Lattice documentation that indicates that registers are initialized to 0

Page 5 of the iCE40 LP/HX Family Data Sheet says: "Each DFF also connects to a global reset signal that is automatically asserted immediately following device configuration."

from yosys.

laanwj avatar laanwj commented on August 17, 2024

@cliffordwolf I can reproduce it.

Commits:

  • arachne-pnr a94ed39
  • yosys 745d561
  • icestorm c6f1e1f

yosys-ice-experiments:

  • 6d4585b fail.v fails (no reply at all to serial)
  • 9db2625 fail.v works (sends back "hello\n")

The only change is (that makes it work again):

diff --git a/error/fail.v b/error/fail.v
index 046ddc1..acc9396 100644
--- a/error/fail.v
+++ b/error/fail.v
@@ -84,7 +84,7 @@ module top(input clk,
     reg [8:0] ptr_saved;
     reg [7:0] outb;
     reg outf;
-    reg [2:0] state = S_IDLE;
+    reg [2:0] state;
     reg [7:0] opcode;
     reg [7:0] cpuregs [3:0];

@@ -168,12 +168,10 @@ module top(input clk,
                 state <= S_OP;
             end
         endcase
-    end
-
-    // Reset logic
-    always @(posedge clk) begin
+        // Reset logic
         if (!uart0_reset) begin // Reset UART only for one clock
             uart0_reset <= 1;
+            state <= S_IDLE;
         end
     end

It has no difference on the result of the testbench/simulation, but does on the hardware (iCEstick) .
Could be the unstable-clock-after-reset issue that you mention, but I'm not sure.

@cseed Great!

from yosys.

cliffordwolf avatar cliffordwolf commented on August 17, 2024

Have you pushed 9db2625 yet? I can't see it in your github repo..

from yosys.

laanwj avatar laanwj commented on August 17, 2024

Done!

from yosys.

cliffordwolf avatar cliffordwolf commented on August 17, 2024

At least here testbench_synth_fail and testbench_post_fail both fail for 6d4585b, so it is reproducible in simulation! Therefore this is not an issue with an unstable clock.. I'll investigate further..

from yosys.

cliffordwolf avatar cliffordwolf commented on August 17, 2024

Ok, the problem here is that the FSM subsystem in Yosys does not know anything about initial values. That is also why you do not get a warning for an ignored init attribute for top.state:

yosys  -q -p "synth_ice40 -top top -blif fail.blif" fail.v uart.v
Warning: Wire top._uart0._rx.hh has an unprocessed 'init' attribute.
Warning: Wire top.uart0_reset has an unprocessed 'init' attribute.

After FSM recoding the init value for the state register is gone and S_IDLE state is something like 6'b000001 and 6'b000000 does not code for any valid state in one-hot encoding. So the FSM never starts doing anything. That's also why the problem goes away if you add explicit initialization for the state register.

E.g. adding the (* fsm_encoding = "none" *) attribute works around the problem:

(* fsm_encoding="none" *) reg [2:0] state = S_IDLE;

Now there is also a warning about an ignored init attribute for top.state:

yosys  -q -p "synth_ice40 -top top -blif fail.blif" fail.v uart.v
Warning: Wire top._uart0._rx.hh has an unprocessed 'init' attribute.
Warning: Wire top.state has an unprocessed 'init' attribute.
Warning: Wire top.uart0_reset has an unprocessed 'init' attribute.

Starting with commit b66bf8b the fsm_detect pass now ignores possible state registers when they have an "init" attribute assigned. This should fix the issue.

from yosys.

laanwj avatar laanwj commented on August 17, 2024

from yosys.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.