FPGAwars / icestudio

:snowflake: Visual editor for open FPGA boards
https://icestudio.io
GNU General Public License v2.0
1.7k stars 245 forks source link

Problem with using localparam during building. RS232 implementation Tinyfpga BX #411

Open DavidGoedicke opened 4 years ago

DavidGoedicke commented 4 years ago

The following lines of code cause the system to not build. The verification works.

function integer log2; input integer v; begin log2=0; while(v>>log2) begin log2=log2+1; end end endfunction localparam l2o = log2(Oversampling); reg [l2o-2:0] OversamplingCnt = 0;

I am trying to implement fpga4fun-serialinterface

Sending bytes works fine. However, receiving bytes does not work. It also does not work if I hard-code the above problematic line.

I am new to FPGA and Verilog and so I'll attach my files but any pointers on how to debug this problem would be much appreciated.

best wishes DG

RS232_RecieverSender.ice.zip

Details:

Consol output

export APIO_HOME_DIR=/Users/dg/.icestudio/apio; "/Users/dg/.icestudio/venv/bin/apio" build --board TinyFPGA-BX --verbose-arachne -p "/var/folders/l1/kck90q_177g8lpdz99njl07m0000gn/T/icestudio-31628IcBTD1EQFcak"

[Mon May 18 21:00:53 2020] Processing TinyFPGA-BX
--------------------------------------------------------------------------------
yosys -p "synth_ice40 -blif hardware.blif" -q main.v
ERROR: Assert `range_left >= range_right || (range_left == -1 && range_right == 0)' failed in frontends/ast/genrtlil.cc:872.
scons: *** [hardware.blif] Error 1
========================= [ ERROR ] Took 0.39 seconds =========================
Obijuan commented 4 years ago

This is weird! It should work. I've been able to reproduce it. I will try to isolate the problem to understand what is going on. I will tell you my findings

I am testing using icestudio 0.5.1n200403-dev in Linux

As a workaround, you can just hardcode the Oversampling value constant in the code:

localparam l2o = log2(16);

It will let you synthesize the design

Obijuan commented 4 years ago

This is the minimal circuit for reproducing the bug:

image

Icestudio File:
bug-min.zip

The verification pass ok, but when sinthesizing this error show up:

bug-screenshot

This is the verilog code generated:

// Code generated by Icestudio 0.5.1n200403
// Wed, 20 May 2020 09:58:10 GMT

`default_nettype none

module main #(
 parameter v7f7647 = 16
) (
 output [7:0] vb2d82b
);
 localparam p1 = v7f7647;
 wire [0:7] w0;
 assign vb2d82b = w0;
 main_v180e25 #(
  .N(p1)
 ) v180e25 (
  .o(w0)
 );
endmodule

module main_v180e25 #(
 parameter N = 0
) (
 output [7:0] o
);
 localparam M=$clog2(N);  //-- M = 4
 localparam K = (M-2);    //-- K = 2

 wire [K:0] test = K;     //-- Test = 010

 //-- Error: Signal '\test' with invalid width range -1!
endmodule

This generated code seems to be ok (iverilator pass)... so maybe the problem is that there is a bug in the yosys version we are using. This version is:

Yosys 0.9+932 (git sha1 UNKNOWN, x86_64-linux-gnu-g++ 7.3.0-16ubuntu3 -O3 -DNDEBUG)

Obijuan commented 4 years ago

All right! I've found the problem! Icestudio by default assign a default value of 0, so in the first pass, yosys uses N = 0 and the $clog2(0) function fails, assigning -1 to M
That can be fixed just by adding a default value different from 0. It cannot be done directly in Studio yet, but this is how can be solved in the previous example:

image

A new constant is created with etither the parameterized N value or 16 for de default value. Now it synthesizes ok.

In the case of your RS232-RecierverSender we can declare a second constant: Oversamplig2 that includes de default value and use it for calling the log2 function

//-- Set the default value for oversampling localparam Oversampling2 = (Oversampling==0) ? 16 : Oversampling; localparam l2o = log2(Oversampling2);

The rest of the code is the same than before.

This is the fixed circuit (I have not test if it works, just that it synthesized with no error):

RS232_RecieverSender-fixed.zip

When you test it leave a comment here and I will close this issue

DavidGoedicke commented 4 years ago

Thank you for looking at it. I will try out the changes later today.

A quick "understanding" question: The $clog2() function should work the same as the one that was written in the code (log2)?

Obijuan commented 4 years ago

A quick "understanding" question: The $clog2() function should work the same as the one that was written in the code (log2)?

Yes. The $clog2() is the verilog system function for that