[prim_pad_wrapper] Update pad wrapper This updates the pad wrapper to better reflect the ASIC pad we are going to use. Specifically, the following changes are made: - an input buffer enable signal is added - a variant parameter is added which allows us to differentiate between different pad implementations for the same technology node - a warl_o signal is added. this signal is constant and defines which attributes are supported by a specific pad wrapper configuration. - the WarlOnly parameter is added for use together with warl_o - additional pad attributes such as schmitt trigger enable and slew rate are added - the pull-up/pull-down attributes are re-encoded such that no invalid configuration can be set where both pull-up and pull-down are activated Signed-off-by: Michael Schaffner <msf@opentitan.org>
diff --git a/hw/ip/prim_generic/rtl/prim_generic_pad_wrapper.sv b/hw/ip/prim_generic/rtl/prim_generic_pad_wrapper.sv index ecf3354..962d3b5 100644 --- a/hw/ip/prim_generic/rtl/prim_generic_pad_wrapper.sv +++ b/hw/ip/prim_generic/rtl/prim_generic_pad_wrapper.sv
@@ -8,46 +8,87 @@ `include "prim_assert.sv" module prim_generic_pad_wrapper #( - parameter int unsigned AttrDw = 6 + parameter int Variant = 0, // currently ignored + parameter int AttrDw = 10, + parameter bit WarlOnly = 0 // If set to 1, no pad is instantiated and only warl_o is driven ) ( inout wire inout_io, // bidirectional pad output logic in_o, // input data + input ie_i, // input enable input out_i, // output data input oe_i, // output enable - // additional attributes {drive strength, keeper, pull-up, pull-down, open-drain, invert} - input [AttrDw-1:0] attr_i + // additional attributes + input [AttrDw-1:0] attr_i, + output logic [AttrDw-1:0] warl_o ); - // get pad attributes - logic kp, pu, pd, od, inv; - typedef enum logic {STRONG_DRIVE = 1'b0, WEAK_DRIVE = 1'b1} drv_e; - drv_e drv; - assign {drv, kp, pu, pd, od, inv} = attr_i[5:0]; + // Supported attributes: + // [x] Bit 0: input/output inversion, + // [x] Bit 1: Virtual open drain enable. + // [x] Bit 2: Pull enable. + // [x] Bit 3: Pull select (0: pull down, 1: pull up). + // [x] Bit 4: Keeper enable. + // [ ] Bit 5: Schmitt trigger enable. + // [ ] Bit 6: Slew rate (0: slow, 1: fast). + // [x] Bit 7/8: Drive strength (00: weakest, 11: strongest). + // [ ] Bit 9: Reserved. + assign warl_o = AttrDw'(10'h19F); - // input inversion - assign in_o = inv ^ inout_io; + if (WarlOnly) begin : gen_warl + assign inout_io = 1'bz; + assign in_o = 1'b0; - // virtual open drain emulation - logic oe, out; - assign out = out_i ^ inv; - assign oe = oe_i & ((od & ~out) | ~od); + logic [AttrDw-1:0] unused_attr; + logic unused_ie, unused_oe, unused_out, unused_inout; + assign unused_ie = ie_i; + assign unused_oe = oe_i; + assign unused_out = out_i; + assign unused_attr = attr_i; + assign unused_inout = inout_io; + end else begin : gen_pad + // get pad attributes + logic unused_sm, kp, unused_sr, ps, pe, od, inv; + typedef enum logic [1:0] {DRIVE_00 = 2'b00, + DRIVE_01 = 2'b01, + DRIVE_10 = 2'b10, + DRIVE_11 = 2'b11} drv_e; + drv_e drv; + assign {drv, unused_sr, unused_sm, kp, ps, pe, od, inv} = attr_i[8:0]; -// driving strength attributes are not supported by verilator + if (AttrDw > 9) begin : gen_unused_attr + logic [AttrDw-9-1:0] unused_attr; + assign unused_attr = attr_i[AttrDw-1:9]; + end + + // input inversion + logic in; + assign in = inv ^ inout_io; + + // virtual open drain emulation + logic oe, out; + assign out = out_i ^ inv; + assign oe = oe_i & ((od & ~out) | ~od); + + // driving strength attributes are not supported by verilator `ifdef VERILATOR - assign inout_io = (oe) ? out : 1'bz; + assign inout_io = (oe) ? out : 1'bz; + // received data driver + assign in_o = (ie_i) ? in : 1'bz; `else - // different driver types - assign (strong0, strong1) inout_io = (oe && drv == STRONG_DRIVE) ? out : 1'bz; - assign (pull0, pull1) inout_io = (oe && drv == WEAK_DRIVE) ? out : 1'bz; - // pullup / pulldown termination - // default to high-Z in case both PU and PD are asserted (safety mechanism). - assign (highz0, weak1) inout_io = pu & ~pd; - assign (weak0, highz1) inout_io = pu | ~pd; - // fake trireg emulation - assign (weak0, weak1) inout_io = (kp) ? inout_io : 1'bz; + // different driver types + assign (strong0, strong1) inout_io = (oe && drv != DRIVE_00) ? out : 1'bz; + assign (pull0, pull1) inout_io = (oe && drv == DRIVE_00) ? out : 1'bz; + // pullup / pulldown termination + assign (highz0, weak1) inout_io = pe & ps; // enabled and select = 1 + assign (weak0, highz1) inout_io = pe & ~ps; // enabled and select = 0 + // fake trireg emulation + assign (weak0, weak1) inout_io = (kp) ? inout_io : 1'bz; + // received data driver + assign in_o = (ie_i) ? in : 1'bz; `endif + end // assertions - `ASSERT_INIT(AttrDwCheck_A, AttrDw >= 7) + `ASSERT_INIT(AttrDwCheck_A, AttrDw >= 9) endmodule : prim_generic_pad_wrapper
diff --git a/hw/ip/prim_xilinx/rtl/prim_xilinx_pad_wrapper.sv b/hw/ip/prim_xilinx/rtl/prim_xilinx_pad_wrapper.sv index 57e9bb4..f9649dd 100644 --- a/hw/ip/prim_xilinx/rtl/prim_xilinx_pad_wrapper.sv +++ b/hw/ip/prim_xilinx/rtl/prim_xilinx_pad_wrapper.sv
@@ -7,37 +7,72 @@ module prim_xilinx_pad_wrapper #( - parameter int unsigned AttrDw = 2 + parameter int Variant = 0, // currently ignored + parameter int AttrDw = 10, + parameter bit WarlOnly = 0 // If set to 1, no pad is instantiated and only warl_o is driven ) ( inout wire inout_io, // bidirectional pad output logic in_o, // input data + input ie_i, // input enable input out_i, // output data input oe_i, // output enable // additional attributes - input [AttrDw-1:0] attr_i + input [AttrDw-1:0] attr_i, + output logic [AttrDw-1:0] warl_o ); - // get pad attributes - logic od, inv; - assign {od, inv} = attr_i[1:0]; + // Supported attributes: + // [x] Bit 0: input/output inversion, + // [x] Bit 1: Virtual open drain enable. + // [ ] Bit 2: Pull enable. + // [ ] Bit 3: Pull select (0: pull down, 1: pull up). + // [ ] Bit 4: Keeper enable. + // [ ] Bit 5: Schmitt trigger enable. + // [ ] Bit 6: Slew rate (0: slow, 1: fast). + // [ ] Bit 7/8: Drive strength (00: weakest, 11: strongest). + // [ ] Bit 9: Reserved. + assign warl_o = AttrDw'(2'h3); - // input inversion - logic in; - assign in_o = inv ^ in; + if (WarlOnly) begin : gen_warl + assign inout_io = 1'bz; + assign in_o = 1'b0; - // virtual open drain emulation - logic oe_n, out; - assign out = out_i ^ inv; - // oe_n = 0: enable driver - // oe_n = 1: disable driver - assign oe_n = ~oe_i | (out & od); + logic [AttrDw-1:0] unused_attr; + logic unused_ie, unused_oe, unused_out, unused_inout; + assign unused_ie = ie_i; + assign unused_oe = oe_i; + assign unused_out = out_i; + assign unused_attr = attr_i; + assign unused_inout = inout_io; + end else begin : gen_pad - // driver - IOBUF i_iobuf ( - .T(oe_n), - .I(out), - .O(in), - .IO(inout_io) - ); + // get pad attributes + logic od, inv; + assign {od, inv} = attr_i[1:0]; + + if (AttrDw > 9) begin : gen_unused_attr + logic [AttrDw-9-1:0] unused_attr; + assign unused_attr = attr_i[AttrDw-1:9]; + end + + // input inversion and buffer + logic in; + assign in_o = (ie_i) ? inv ^ in : 1'bz; + + // virtual open drain emulation + logic oe_n, out; + assign out = out_i ^ inv; + // oe_n = 0: enable driver + // oe_n = 1: disable driver + assign oe_n = ~oe_i | (out & od); + + // driver + IOBUF i_iobuf ( + .T ( oe_n ), + .I ( out ), + .O ( in ), + .IO ( inout_io ) + ); + end endmodule : prim_xilinx_pad_wrapper