chipsalliance / f4pga-examples

Example designs showing different ways to use F4PGA toolchains.
https://f4pga-examples.readthedocs.io
Apache License 2.0
267 stars 77 forks source link

SYMBIFLOW-CLASSROOM Surelog/UHDM and enum's #291

Closed nelsobe closed 2 years ago

nelsobe commented 2 years ago

In the code below there are two typedefs with enums in them (they are preceded with comments).

Both work in Vivado and in the Yosys front end.

However the Surelog/UHDM front end doesn't handle the first variation correctly. With it, the synthesis log suggests it has reduced the 'cs' signal to be just one bit wide instead of two.

`default_nettype none
module debounce(
    input wire logic clk,
    input wire logic reset,
    input wire logic noisy, 
    output logic debounced,
    output logic[1:0] st
);
    parameter WAIT_TIME_US = 5000;
    localparam CLK_PERIOD_NS = 10;
    localparam /*integer*/ TIMER_CLOCK_COUNT = WAIT_TIME_US * 1000 / CLK_PERIOD_NS;

    localparam WAIT_BITS = $clog2(TIMER_CLOCK_COUNT);

    reg [WAIT_BITS-1:0] counter = 0;

    wire clrTimer;
    reg timerDone;

    // Using this typedef for StateType, the design does not work with Surelog/UHDM but does with Vivado and Yosys front ends.
    typedef enum {S0, S1, S2, S3, ERR='x} StateType;

    // Using this typedef for StateType, the design does work with Surelog/UHDM, the synthesis log shows 'cs' is a 2-bit signal.
    //typedef enum logic[1:0] {S0, S1, S2, S3, ERR='x} StateType;

    StateType cs, ns;
    assign st = cs;

    // State Machine
    always @(posedge clk)
    begin
        if (reset)
            cs <= S0;
        else
            cs <= ns;
    end

    always_comb begin
        ns = ERR;
        case(cs)
            S0:
                if (noisy)
                    ns = S1;
                else    
                    ns = S0;
            S1:
                if (! noisy)
                    ns = S0;
                else if (timerDone)
                    ns = S2;
                else 
                    ns = S1;                
            S2:
                if (! noisy)
                    ns = S3;
                else
                    ns = S2;
            S3:
                if (noisy)
                    ns = S2;
                else if (timerDone)
                    ns = S0;
                else
                    ns = S3;
        endcase
    end

    assign debounced = (cs == S2 || cs == S3);
    assign clrTimer = (cs == S2 || cs == S0);

    // Create counter (behavorial)
    always_ff @(posedge clk)
    begin
        if (clrTimer || reset)
            counter <= 0;
        else
            counter <= counter + 1;
    end

    assign timerDone = (counter == TIMER_CLOCK_COUNT);

endmodule
rkapuscik commented 2 years ago

This should be already fixed, please update the plugin to the newest version as described here to verify.

westonMS commented 2 years ago

We have re-tested this with the latest plugin and the design works now. However, we want fixes to be available to all users when they use the main install. I re-installed the tool-chain with the latest install instructions and this is not fixed without manually updating the plugin.

mithro commented 2 years ago

FYI - @kgugala