Search code examples
yosys

Yosys: Variable initial value to flip-flop at reset


I am trying to assign an initial value to the FF at reset. The initial value is an input to the circuit. In the cell library I added the following FF:

cell (DFF){
    area    : 0;
    ff(IQ,IQN){
        next_state  : "D";
        clocked_on  : "CLK";
        clear   : "I'*RST";
        preset  : "I*RST";
        clear_preset_var1   : L;
    }
    pin(CLK){
        direction   : input;
        capacitance : 0;
        clock   : true;
    }
    pin(RST){
        direction   : input;
        capacitance : 0;
    }
    pin(D){
        direction   : input;
        capacitance : 0;
        timing() {
          related_pin   : "CLK";
        }
    }
    pin(I){
        direction   : input;
        capacitance : 0;
    }
    pin(Q){
        direction   : output;
        function    : "IQ";
        timing() {
          related_pin   : "CLK";
          timing_type   : falling_edge;
        }
        timing() {
            related_pin : "RST";
            timing_type : clear;
            timing_sense    : positive_unate;
        }
        timing() {
            related_pin : "I";
            timing_type : clear;
            timing_sense    : negative_unate;
        }
        timing() {
            related_pin : "RST";
            timing_type : preset;
            timing_sense    : positive_unate;
        }
        timing() {
            related_pin : "I";
            timing_type : preset;
            timing_sense    : positive_unate;
        }
    }
}

The part of the Verilog code that I am trying to synthesize to this FF is

    always@(posedge clk or posedge rst)
    if(rst) begin 
        e_reg <= e_input;
    end
    else begin 
        e_reg <= e_shift;
    end 

However, when I run the synthesis, it uses one of the built-in FFs from the Yosys library ($_DFFSR_PPP_) ignoring the one from the user-defined cell library. If I include one of the set-reset (SR) FFs in the user-defined library, like the following, that is picked up by Yosys.

cell(DFF) {
area: 0;
ff("IQ", "IQN") { clocked_on: CLK;
              next_state: D;
                  preset: I;
                   clear: RST; }
pin(CLK) { direction: input;
             clock: true; }
pin(D) { direction: input; }
pin(Q) { direction: output;
          function: "IQ"; }
pin(I) { direction: input; }
pin(RST) { direction: input; }
}

The earlier one works with Synopsys DC, but not with Yosys. It seems that the equations in clear or preset are not being picked up by Yosys.

In there any way to make it work? Am I missing something?

EDIT: I am adding a complete example in case anyone wants to run this.

acc.v

module acc #(parameter N = 1)( 
    input clk,
    input rst,
    input [N-1:0] a,
    input [N-1:0] b,
    output [N-1:0] o
);

    logic [N-1:0] o_reg;

    assign o = o_reg & a;

    always@(posedge clk or posedge rst) begin
        if(rst) o_reg <= b;
        else o_reg <= o;
    end 

endmodule

asic_cell_yosys.lib

library(demo) {
    cell(IV) {
        area: 1;
        pin(A) { direction: input; }
        pin(Z) { direction: output; function: "A'"; }
    }
    cell(AND) {
        area: 1;
        pin(A) { direction: input; }
        pin(B) { direction: input; }
        pin(Z) { direction: output; function: "(A&B)"; }
    }   
    cell(NAND) {
        area: 1;
        pin(A) { direction: input; }
        pin(B) { direction: input; }
        pin(Z) { direction: output; function: "(A&B)'"; }
    }
    cell(DFFSR) {
        area: 4;
        ff("IQ", "IQN"){clocked_on: C;
                        next_state: D;
                        preset: S;
                        clear: R; }
        pin(C) { direction: input;
                     clock: true; }
        pin(D) { direction: input; }
        pin(Q) { direction: output;
                  function: "IQ"; }
        pin(S) { direction: input; }
        pin(R) { direction: input; }
    }
}

acc.tcl

yosys -import
read_verilog -sv acc.sv
hierarchy -check -top acc 
procs; opt; flatten; opt; 
techmap; opt;
dfflibmap -liberty asic_cell_yosys.lib
abc -liberty asic_cell_yosys.lib -script +map; 
opt; clean; opt;
opt_clean -purge
write_verilog -noattr -noexpr -nohex acc_syn.v

Solution

  • Yosys' dfflibmap doesn't support expressions such as this for clear or preset in a Liberty file.

    However, you could use the techmap command with a custom-made map rule to map $_DFFSR_PPP_ to your own flipflop - similar to how we do FPGA techmapping in Yosys.

    As an example of this. Create dffsr_map.v:

    module $_DFFSR_PPP_(input C, S, R, D, output Q);
        DFFSR _TECHMAP_REPLACE_ (.CLK(C), .RST(S | R), .I(S), .D(D), .Q(Q));    
    endmodule
    

    and add techmap -map dffsr_map.v -map +/techmap.v after dfflibmap