1
\$\begingroup\$

I know that the code I am going a publush is terrible and pointless, just I am playing trying to go deep in verilog, deep to gate behaviour... Well, this is the pain code:

module syncRX(clk, signal, detect);
    input clk, signal;
    output wire [7:0] detect;
    
    reg rst = 0;
    reg [7:0] counter = 0;
    wire [7:0] aux;
    
    freq_div div(.clk(clk), .clk_1khz(clk_1khz));
    
    rsff rs0(.r(rst), .s(aux[0]), .q(detect[0]));
    rsff rs1(.r(rst), .s(aux[1]), .q(detect[1]));
    rsff rs2(.r(rst), .s(aux[2]), .q(detect[2]));
    rsff rs3(.r(rst), .s(aux[3]), .q(detect[3]));
    rsff rs4(.r(rst), .s(aux[4]), .q(detect[4]));
    rsff rs5(.r(rst), .s(aux[5]), .q(detect[5]));
    rsff rs6(.r(rst), .s(aux[6]), .q(detect[6]));
    rsff rs7(.r(rst), .s(aux[7]), .q(detect[7]));
    
    always @(posedge signal or posedge clk_1khz)
        if(signal == 1'b1)
            begin
                rst = 1;
                rst = 0;
                aux <= counter;
                counter <= 0;
            end
        else
            counter <= counter + 1;
        
endmodule // top

module freq_div(input clk, output reg clk_1khz);
    reg [18:0] count = 0;
    always @(posedge clk)
     begin
        if(count == 60000)
            begin
                clk_1khz <= ~clk_1khz;
                count <= 0;
            end
        else
            count <= count + 1;
     end
endmodule

module rsff(r, s, q);

    input r,s;
    output q;

    nand(~s,qbar,q);
    nand(~r,q,qbar);

endmodule

The idea is to take a "snapshot" of the counter before reset it, being this "snapshot" the output of the module (I know there is an other way to do, but I want to solve in gate level). I am using an ICE40 FPGA and it should show a 8 bit binary number in the leds representing the cycle of "signal" counted by "clk_1khz". I got an timming error. But can not find out why... Thanks.

Append: The error:

nextpnr-ice40 --hx8k --package tq144:4k --json syncRX.json --pcf syncRX.pcf --asc syncRX.asc


Info: constrained 'signal' to bel 'X0/Y25/io1'
Info: constrained 'detect[0]' to bel 'X12/Y0/io1'
Info: constrained 'detect[1]' to bel 'X12/Y0/io0'
Info: constrained 'detect[2]' to bel 'X11/Y0/io1'
Info: constrained 'detect[3]' to bel 'X8/Y0/io0'
Info: constrained 'detect[4]' to bel 'X7/Y0/io1'
Info: constrained 'detect[5]' to bel 'X6/Y0/io1'
Info: constrained 'detect[6]' to bel 'X4/Y0/io1'
Info: constrained 'detect[7]' to bel 'X4/Y0/io0'
Info: constrained 'clk' to bel 'X16/Y0/io1'

Info: Packing constants..
Info: Packing IOs..
Info: Packing LUT-FFs..
Info:        0 LCs used as LUT4 only
Info:        0 LCs used as LUT4 and DFF
Info: Packing non-LUT FFs..
Info:        0 LCs used as DFF only
Info: Packing carries..
Info:        0 LCs used as CARRY only
Info: Packing RAMs..
Info: Placing PLLs..
Info: Packing special functions..
Info: Promoting globals..
Info: Constraining chains...
Info:        0 LCs used to legalise carry chains.
Info: Checksum: 0xd7159a06

Info: Annotating ports with timing budgets for target frequency 12.00 MHz
Info: Checksum: 0x8078c586

Info: Device utilisation:
Info:            ICESTORM_LC:     1/ 7680     0%
Info:           ICESTORM_RAM:     0/   32     0%
Info:                  SB_IO:    10/  256     3%
Info:                  SB_GB:     0/    8     0%
Info:           ICESTORM_PLL:     0/    2     0%
Info:            SB_WARMBOOT:     0/    1     0%

Info: Placed 10 cells based on constraints.
Info: Creating initial analytic placement for 0 cells, random placement wirelen = 0.
Info:     at initial placer iter 0, wirelen = 0
Info:     at initial placer iter 1, wirelen = 0
Info:     at initial placer iter 2, wirelen = 0
Info:     at initial placer iter 3, wirelen = 0
Info: Running main analytical placer.
Info: HeAP Placer Time: 0.00s
Info:   of which solving equations: 0.00s
Info:   of which spreading cells: 0.00s
Info:   of which strict legalisation: 0.00s

Info: Running simulated annealing placer for refinement.
Info:   at iteration #1: temp = 0.000000, timing cost = 0, wirelen = 0
Info:   at iteration #2: temp = 0.000000, timing cost = 0, wirelen = 0
Info: SA placement time 0.00s
Warning: No clocks found in design

Info: Checksum: 0xe3e91e09

Info: Routing..
Info: Setting up routing queue.
Info: Routing 0 arcs.
Info:            |   (re-)routed arcs  |   delta    | remaining
Info:    IterCnt |  w/ripup   wo/ripup |  w/r  wo/r |      arcs
Info:          0 |        0          0 |    0     0 |         0
Info: Routing complete.
Info: Route time 0.00s
Info: Checksum: 0x0a0c3218
Warning: No clocks found in design

Expected waveform

Pretended schematic

I can not underestand why the code with this modification works...

module syncRX(clk, signal, detect);
    input clk, signal;
    output wire [7:0] detect;
    
    reg rst = 0;
    reg [7:0] counter = 0;
    wire [7:0] aux;
    
    assign detect = counter;
    
    freq_div div(.clk(clk), .clk_1khz(clk_1khz));
    
    rsff rs0(.r(rst), .s(aux[0]), .q(detect[0]));
    rsff rs1(.r(rst), .s(aux[1]), .q(detect[1]));
    rsff rs2(.r(rst), .s(aux[2]), .q(detect[2]));
    rsff rs3(.r(rst), .s(aux[3]), .q(detect[3]));
    rsff rs4(.r(rst), .s(aux[4]), .q(detect[4]));
    rsff rs5(.r(rst), .s(aux[5]), .q(detect[5]));
    rsff rs6(.r(rst), .s(aux[6]), .q(detect[6]));
    rsff rs7(.r(rst), .s(aux[7]), .q(detect[7]));
    
    always @(posedge signal or posedge clk_1khz)
        if(signal == 1'b1)
            begin
                rst = 1;
                rst = 0;
                aux <= counter;
                counter <= 0;
            end
        else
            counter <= counter + 1;
        
endmodule // top

Thanks

\$\endgroup\$
6
  • 2
    \$\begingroup\$ Please include the exact text of the error message you got. \$\endgroup\$
    – The Photon
    Aug 25, 2020 at 17:48
  • \$\begingroup\$ @ThePhoton sure! I add the full log in the question (is too big for a comment). Thanks! \$\endgroup\$
    – Carlos J.
    Aug 25, 2020 at 19:32
  • \$\begingroup\$ Where is the timing error? \$\endgroup\$
    – The Photon
    Aug 25, 2020 at 21:26
  • \$\begingroup\$ One thing I'll point out is that where you have rst = 1; rst = 0; That will probably just synthesize to rst being set to zero. It won't generate a pulse on rst to trigger the RS flops. You probably want to set rst to 1 when the signal goes high, and then find a way to return it to zero after some controlled delay. Exactly how to do that depends on what you're trying to achieve. \$\endgroup\$
    – The Photon
    Aug 25, 2020 at 21:30
  • \$\begingroup\$ @ThePhoton I am using Icestorm tools and it seams too gentle with errors, it compile but FPGA is doing nothing, but if comment the line 25 "//aux <= counter;" and add bellow line 7 "assign detect = counter;" not only compile, the FPGA works as a counter. Then I take the "Warning: No clocks found in design" as an error (always when I get this warning everything stop working) \$\endgroup\$
    – Carlos J.
    Aug 26, 2020 at 11:38

1 Answer 1

1
\$\begingroup\$

The problem is here:

always @(posedge signal or posedge clk_1khz)
    if(signal == 1'b1)
        begin
            rst = 1;
            rst = 0;
            aux <= counter; // Here
            counter <= 0;
        end
    else
        counter <= counter + 1;

You are using signal as a reset for the flip-flops that produce counter, which is perfectly all right.

But for aux you are trying to have two different clock inputs (signal and clk_1khz) trigger it capture the value from counter. As we discussed in your previous question, that isn't synthesizable.

You also have a problem with rst: You can't synthesize two different transitions of the signal on the same clock edge. In synthesis, the net result of rst = 1; rst = 0; will just be to set rst low. Meaning that rst will simply never go high. You should find a way to set it high when the reset (signal) occurs, and then set it low after signal goes low again.

\$\endgroup\$
10
  • \$\begingroup\$ Thanks a lot. Just a question "rst = 0;" is blocking. This dont mean that have to commit the action before happends the next line? because in that case should give a signal. \$\endgroup\$
    – Carlos J.
    Aug 26, 2020 at 15:09
  • \$\begingroup\$ about aux is in two different clock, I see counter in two different clock but not aux (is not a critic, just ask because maybe you saw something I didnt), anyway they are handled inside a "IF" stament, then should be synthetizable... I guess. Thanks a lot for your hel, and for be patient with my, I still have to learn a lot about this technology \$\endgroup\$
    – Carlos J.
    Aug 26, 2020 at 15:16
  • \$\begingroup\$ @CarlosJ., when either signal or clk_1khz has a rising edge, aux gets the value from counter. That's two different clocks controlling aux and it isn't synthesizable. You can use an if-statement to generate reset logic, but only if you assign the value from a constant (not another signal) inside the if-statement. \$\endgroup\$
    – The Photon
    Aug 26, 2020 at 15:19
  • \$\begingroup\$ your answer make sense... Do you think that change the "else" to "else if(clk_1khz == 1'b1)" could solve the situation? (with this modification would never "aux" be controlled in the same time). Thanks! \$\endgroup\$
    – Carlos J.
    Aug 27, 2020 at 12:31
  • \$\begingroup\$ No, was not good idea, is not even compiling... and also, is not making even logical diference... Anyway, I think I didnt get your point, there is two edges, but also there is an "if - else" structure, is going never a be modificate "aux" in the same time bought edges... Maybe I am missing something... \$\endgroup\$
    – Carlos J.
    Aug 27, 2020 at 12:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.