[pad_wrapper] Extend the generic and Xilinx pad wrapper models
Signed-off-by: Michael Schaffner <msf@google.com>
diff --git a/hw/ip/prim/rtl/prim_pad_wrapper_pkg.sv b/hw/ip/prim/rtl/prim_pad_wrapper_pkg.sv
index 7b16642..08057ac 100644
--- a/hw/ip/prim/rtl/prim_pad_wrapper_pkg.sv
+++ b/hw/ip/prim/rtl/prim_pad_wrapper_pkg.sv
@@ -4,11 +4,12 @@
package prim_pad_wrapper_pkg;
- typedef enum logic [1:0] {
- BidirStd = 2'h0, // Standard bidirectional pad
- BidirTol = 2'h1, // Voltage tolerant pad
- BidirOd = 2'h2, // Open-drain capable pad
- InputStd = 2'h3 // Input-only pad
+ typedef enum logic [2:0] {
+ BidirStd = 3'h0, // Standard bidirectional pad
+ BidirTol = 3'h1, // Voltage tolerant pad
+ BidirOd = 3'h2, // Open-drain capable pad
+ InputStd = 3'h3, // Input-only pad
+ AnalogIn0 = 3'h4 // Analog input pad
} pad_type_e;
typedef enum logic [1:0] {
diff --git a/hw/ip/prim_generic/rtl/prim_generic_pad_attr.sv b/hw/ip/prim_generic/rtl/prim_generic_pad_attr.sv
index 23ef717..3d14b75 100644
--- a/hw/ip/prim_generic/rtl/prim_generic_pad_attr.sv
+++ b/hw/ip/prim_generic/rtl/prim_generic_pad_attr.sv
@@ -15,6 +15,13 @@
// Currently supported pad attributes of the generic pad library:
//
+ // Input-only:
+ //
+ // - inversion
+ // - pullup / pulldown
+ //
+ // Bidirectional:
+ //
// - inversion
// - virtual open drain
// - keeper
@@ -22,18 +29,42 @@
// - 1 driving strength bit
//
// Note that the last three attributes are not supported on Verilator.
- always_comb begin : p_attr
- attr_warl_o = '0;
- attr_warl_o.invert = 1'b1;
- attr_warl_o.virt_od_en = 1'b1;
- attr_warl_o.keep_en = 1'b1;
-// Driving strength and pulls are not supported by Verilator
-`ifndef VERILATOR
- attr_warl_o.pull_en = 1'b1;
- attr_warl_o.pull_select = 1'b1;
- // Only one driving strength bit is supported.
- attr_warl_o.drive_strength[0] = 1'b1;
-`endif
+ if (PadType == InputStd) begin : gen_input_only_warl
+ always_comb begin : p_attr
+ attr_warl_o = '0;
+ attr_warl_o.invert = 1'b1;
+ // Driving strength and pulls are not supported by Verilator
+ `ifndef VERILATOR
+ attr_warl_o.pull_en = 1'b1;
+ attr_warl_o.pull_select = 1'b1;
+ `endif
+ end
+ end else if (PadType == BidirStd ||
+ PadType == BidirTol ||
+ PadType == BidirOd) begin : gen_bidir_warl
+ always_comb begin : p_attr
+ attr_warl_o = '0;
+ attr_warl_o.invert = 1'b1;
+ attr_warl_o.virt_od_en = 1'b1;
+ attr_warl_o.keep_en = 1'b1;
+ // Driving strength and pulls are not supported by Verilator
+ `ifndef VERILATOR
+ attr_warl_o.pull_en = 1'b1;
+ attr_warl_o.pull_select = 1'b1;
+ // Only one driving strength bit is supported.
+ attr_warl_o.drive_strength[0] = 1'b1;
+ `endif
+ end
+ end else if (PadType == AnalogIn0) begin : gen_analog0_warl
+ // The analog pad type is basically just a feedthrough,
+ // and does hence not support any of the attributes.
+ always_comb begin : p_attr
+ attr_warl_o = '0;
+ end
+ end else begin : gen_invalid_config
+ // this should throw link warnings in elaboration
+ assert_static_in_generate_config_not_available
+ assert_static_in_generate_config_not_available();
end
endmodule : prim_generic_pad_attr
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 11d3151..59a402d 100644
--- a/hw/ip/prim_generic/rtl/prim_generic_pad_wrapper.sv
+++ b/hw/ip/prim_generic/rtl/prim_generic_pad_wrapper.sv
@@ -29,6 +29,9 @@
input pad_attr_t attr_i // additional pad attributes
);
+ // analog pads cannot have a scan role.
+ `ASSERT_INIT(AnalogNoScan_A, PadType != AnalogIn0 || ScanRole == NoScan)
+
// not all signals are used here.
logic unused_sigs;
assign unused_sigs = ^{attr_i.slew_rate,
@@ -38,26 +41,59 @@
scanmode_i,
pok_i};
- assign in_raw_o = (ie_i) ? inout_io : 1'bz;
- // input inversion
- assign in_o = attr_i.invert ^ in_raw_o;
+ if (PadType == InputStd) begin : gen_input_only
+ logic unused_sigs;
+ assign unused_sigs = ^{out_i,
+ oe_i,
+ attr_i.virt_od_en,
+ attr_i.drive_strength};
- // virtual open drain emulation
- logic oe, out;
- assign out = out_i ^ attr_i.invert;
- assign oe = oe_i & ((attr_i.virt_od_en & ~out) | ~attr_i.virt_od_en);
+ assign in_raw_o = (ie_i) ? inout_io : 1'bz;
+ // input inversion
+ assign in_o = attr_i.invert ^ in_raw_o;
-// drive strength attributes are not supported by verilator
-`ifdef VERILATOR
- assign inout_io = (oe) ? out : 1'bz;
-`else
- // different driver types
- assign (strong0, strong1) inout_io = (oe && attr_i.drive_strength[0]) ? out : 1'bz;
- assign (pull0, pull1) inout_io = (oe && !attr_i.drive_strength[0]) ? out : 1'bz;
- // pullup / pulldown termination
- assign (weak0, weak1) inout_io = attr_i.pull_en ? attr_i.pull_select : 1'bz;
- // fake trireg emulation
- assign (weak0, weak1) inout_io = (attr_i.keep_en) ? inout_io : 1'bz;
-`endif
+ // pulls are not supported by verilator
+ `ifndef VERILATOR
+ // pullup / pulldown termination
+ assign (weak0, weak1) inout_io = attr_i.pull_en ? attr_i.pull_select : 1'bz;
+ `endif
+ end else if (PadType == BidirTol ||
+ PadType == BidirOd ||
+ PadType == BidirStd) begin : gen_bidir
+
+ assign in_raw_o = (ie_i) ? inout_io : 1'bz;
+ // input inversion
+ assign in_o = attr_i.invert ^ in_raw_o;
+
+ // virtual open drain emulation
+ logic oe, out;
+ assign out = out_i ^ attr_i.invert;
+ assign oe = oe_i & ((attr_i.virt_od_en & ~out) | ~attr_i.virt_od_en);
+
+ // drive strength attributes are not supported by verilator
+ `ifdef VERILATOR
+ assign inout_io = (oe) ? out : 1'bz;
+ `else
+ // different driver types
+ assign (strong0, strong1) inout_io = (oe && attr_i.drive_strength[0]) ? out : 1'bz;
+ assign (pull0, pull1) inout_io = (oe && !attr_i.drive_strength[0]) ? out : 1'bz;
+ // pullup / pulldown termination
+ assign (weak0, weak1) inout_io = attr_i.pull_en ? attr_i.pull_select : 1'bz;
+ // fake trireg emulation
+ assign (weak0, weak1) inout_io = (attr_i.keep_en) ? inout_io : 1'bz;
+ `endif
+ end else if (PadType == AnalogIn0) begin : gen_analog0
+
+ logic unused_sigs;
+ assign unused_sigs = ^{attr_i, out_i, oe_i, ie_i};
+
+ assign in_o = inout_io;
+ assign in_raw_o = inout_io;
+
+ end else begin : gen_invalid_config
+ // this should throw link warnings in elaboration
+ assert_static_in_generate_config_not_available
+ assert_static_in_generate_config_not_available();
+ end
endmodule : prim_generic_pad_wrapper
diff --git a/hw/ip/prim_xilinx/rtl/prim_xilinx_pad_attr.sv b/hw/ip/prim_xilinx/rtl/prim_xilinx_pad_attr.sv
index 1f1187e..3e10f42 100644
--- a/hw/ip/prim_xilinx/rtl/prim_xilinx_pad_attr.sv
+++ b/hw/ip/prim_xilinx/rtl/prim_xilinx_pad_attr.sv
@@ -14,18 +14,41 @@
output pad_attr_t attr_warl_o
);
- // Currently supporte pad attributes of the Xilinx pad library.
+ // Currently supported pad attributes of the Xilinx pad library.
+ //
+ // Input-only:
+ //
+ // - inversion
+ //
+ // Bidirectional:
//
// - inversion
// - virtual open drain
//
- // TODO: add support for dynamic pull-up/down using the PULLUP/PULLDOWN primitives
- // from the vivado-7series library (https://www.xilinx.com/support/documentation/
- // sw_manuals/xilinx2020_2/ug953-vivado-7series-libraries.pdf)
- always_comb begin : p_attr
- attr_warl_o = '0;
- attr_warl_o.invert = 1'b1;
- attr_warl_o.virt_od_en = 1'b1;
+ if (PadType == InputStd) begin : gen_input_only_warl
+ always_comb begin : p_attr
+ attr_warl_o = '0;
+ attr_warl_o.invert = 1'b1;
+ end
+ end else if (PadType == BidirStd ||
+ PadType == BidirTol ||
+ PadType == BidirOd) begin : gen_bidir_warl
+ always_comb begin : p_attr
+ attr_warl_o = '0;
+ attr_warl_o.invert = 1'b1;
+ attr_warl_o.virt_od_en = 1'b1;
+ end
+ end else if (PadType == Analog0) begin : gen_analog0_warl
+ // The analog pad type is basically just a feedthrough,
+ // and does hence not support any of the attributes.
+ always_comb begin : p_attr
+ attr_warl_o = '0;
+ end
+ end else begin : gen_invalid_config
+ // this should throw link warnings in elaboration
+ assert_static_in_generate_config_not_available
+ assert_static_in_generate_config_not_available();
end
+
endmodule : prim_xilinx_pad_attr
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 58608ff..db0d60b 100644
--- a/hw/ip/prim_xilinx/rtl/prim_xilinx_pad_wrapper.sv
+++ b/hw/ip/prim_xilinx/rtl/prim_xilinx_pad_wrapper.sv
@@ -28,6 +28,9 @@
input pad_attr_t attr_i // additional pad attributes
);
+ // analog pads cannot have a scan role.
+ `ASSERT_INIT(AnalogNoScan_A, PadType != AnalogIn0 || ScanRole == NoScan)
+
// not all signals are used here.
logic unused_sigs;
assign unused_sigs = ^{attr_i.slew_rate,
@@ -40,24 +43,63 @@
scanmode_i,
pok_i};
- // input inversion
- logic in;
- assign in_raw_o = (ie_i) ? in : 1'bz;
- assign in_o = attr_i.invert ^ in_raw_o;
- // virtual open drain emulation
- logic oe_n, out;
- assign out = out_i ^ attr_i.invert;
- // oe_n = 0: enable driver
- // oe_n = 1: disable driver
- assign oe_n = ~oe_i | (out & attr_i.virt_od_en);
+ if (PadType == InputStd) begin : gen_input_only
+ logic unused_sigs;
+ assign unused_sigs = ^{out_i,
+ oe_i,
+ attr_i.virt_od_en};
- // driver
- IOBUF u_iobuf (
- .T ( oe_n ),
- .I ( out ),
- .O ( in ),
- .IO ( inout_io )
- );
+ // input inversion
+ logic in;
+ assign in_raw_o = (ie_i) ? in : 1'bz;
+ assign in_o = attr_i.invert ^ in_raw_o;
+
+ IBUF u_ibuf (
+ .I ( inout_io ),
+ .O ( in )
+ );
+ end else if (PadType == BidirTol ||
+ PadType == BidirOd ||
+ PadType == BidirStd) begin : gen_bidir
+
+ // input inversion
+ logic in;
+ assign in_raw_o = (ie_i) ? in : 1'bz;
+ assign in_o = attr_i.invert ^ in_raw_o;
+
+ // virtual open drain emulation
+ logic oe_n, out;
+ assign out = out_i ^ attr_i.invert;
+ // oe_n = 0: enable driver
+ // oe_n = 1: disable driver
+ assign oe_n = ~oe_i | (out & attr_i.virt_od_en);
+
+ IOBUF u_iobuf (
+ .T ( oe_n ),
+ .I ( out ),
+ .O ( in ),
+ .IO ( inout_io )
+ );
+ end else if (PadType == AnalogIn0) begin : gen_analog0
+
+ logic unused_sigs;
+ assign unused_sigs = ^{out_i,
+ oe_i,
+ attr_i.invert,
+ attr_i.virt_od_en};
+ // this is currently modeled as a logic feed through.
+ IBUF u_ibuf (
+ .I ( inout_io ),
+ .O ( in_raw_o )
+ );
+
+ assign in_raw_o = inout_io;
+
+ end else begin : gen_invalid_config
+ // this should throw link warnings in elaboration
+ assert_static_in_generate_config_not_available
+ assert_static_in_generate_config_not_available();
+ end
endmodule : prim_xilinx_pad_wrapper