Search code examples
verilogyosys

How to simplify compound assignments in yosys


I am trying to get yosys to synthesize my design to structural verilog for a tool which doesn't understand the syntax {A, B} to specify the concatenation of values A and B.

So for example when yosys generates statements like

assign C = {A,B};
assign {D,E} = F;

the tool chokes. I thought of using the splitnets pass to eliminate multibit wires, but the multibit ports still cause yosys to generate the {} syntax. Even running splitnets -ports leaves some assignments like

assign {A, B} = {C, D}

I was finally able to get these assignments to disappear using an additional run of opt. But this seems to be a very messy way of eliminating the {} construct.

Is there some nicer way to eliminate this construct without splitting all the input ports?


Solution

  • There is no universally applicable way to do that. The {..} operator is part of verilog and thus the verilog back-end uses it when appropriate.

    However, in the example you gave all cells in the verilog output have single-bit in- and outputs, so the {..} operator is not needed for assigning cell ports, only for assigning wires to each other.

    I've used the following script (executed in your rtl/ directory) as a baseline:

    read_verilog aes_128.v table.v round.v
    hierarchy -top aes_128
    proc; flatten; synth
    # opt_clean -purge
    write_verilog -noattr -noexpr out.v
    

    This will produce a Verilog file with the following assignments in it that use the {..} operator:

    $ grep '{' out.v
    assign \a1.S4_0.in  = { key[23:0], key[31:24] };
    assign { \a1.k0a [31:25], \a1.k0a [23:0] } = { key[127:121], key[119:96] };
    assign \a1.v0  = { key[127:121], \a1.k0a [24], key[119:96] };
    

    However, the signals a1.S4_0.in, a1.k0a, and a1.v0 are only present in the design because yosys tries to preserve as many of the original signal names as possible, to make it easier to debug the design.

    Un-commenting the opt_clean -purge command will let yosys remove those signals, yielding an output file that does not use the {..} operator:

    $ grep -c '{' out.v 
    0