blob: fc8b3d18341ea6bd2f892512a224eb8a07024fa6 [file] [log] [blame]
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
//
// This it the padctrl portion that has to be instantiated on the chip level.
// The module instantiates the technology dependent pads, and connects them
// to the MIOs/DIOs and pad attributes coming from the padctrl block.
//
`include "prim_assert.sv"
module padring import padctrl_reg_pkg::*; #(
// This allows to selectively connect Pad instances.
// unconnected inputs are tied to 0, unconnected outputs are high-z.
parameter logic [NMioPads-1:0] ConnectMioIn = '1,
parameter logic [NMioPads-1:0] ConnectMioOut = '1,
parameter logic [NDioPads-1:0] ConnectDioIn = '1,
parameter logic [NDioPads-1:0] ConnectDioOut = '1,
// 0: bidir, 1: input, 2: tolerant, 3: open drain
parameter logic [NMioPads-1:0][1:0] MioPadVariant = '0,
parameter logic [NDioPads-1:0][1:0] DioPadVariant = '0
) (
// pad input
input wire clk_pad_i,
input wire clk_usb_48mhz_pad_i,
input wire rst_pad_ni,
// to clocking/reset infrastructure
output logic clk_o,
output logic clk_usb_48mhz_o,
output logic rst_no,
// pads
inout wire [NMioPads-1:0] mio_pad_io,
inout wire [NDioPads-1:0] dio_pad_io,
// muxed IO signals coming from pinmux
output logic [NMioPads-1:0] mio_in_o,
input [NMioPads-1:0] mio_out_i,
input [NMioPads-1:0] mio_oe_i,
// dedicated IO signals coming from peripherals
output logic [NDioPads-1:0] dio_in_o,
input [NDioPads-1:0] dio_out_i,
input [NDioPads-1:0] dio_oe_i,
// pad attributes from top level instance
input [NMioPads-1:0][AttrDw-1:0] mio_attr_i,
input [NDioPads-1:0][AttrDw-1:0] dio_attr_i
);
/////////////////////////
// Clock / Reset Infra //
/////////////////////////
// use this intermediate assignment to make both lint and fpv happy.
// the clock/reset wires should be input-only, otherwise fpv
// has trouble defining/tracing the clock signal. on the other hand, a direct
// connection of input wire to an inout pad causes lint problems
// (even though oe is hardwired to 0).
wire clk, clk_usb_48mhz, rst_n;
assign clk = clk_pad_i;
assign clk_usb_48mhz = clk_usb_48mhz_pad_i;
assign rst_n = rst_pad_ni;
prim_pad_wrapper #(
.AttrDw ( AttrDw ),
.Variant ( 1 ) // input-only
) i_clk_pad (
.inout_io ( clk ),
.in_o ( clk_o ),
.ie_i ( 1'b1 ),
.out_i ( 1'b0 ),
.oe_i ( 1'b0 ),
.attr_i ( '0 ),
.warl_o ( )
);
prim_pad_wrapper #(
.AttrDw ( AttrDw ),
.Variant ( 1 ) // input-only
) i_clk_usb_48mhz_pad (
.inout_io ( clk_usb_48mhz ),
.in_o ( clk_usb_48mhz_o ),
.ie_i ( 1'b1 ),
.out_i ( 1'b0 ),
.oe_i ( 1'b0 ),
.attr_i ( '0 ),
.warl_o ( )
);
prim_pad_wrapper #(
.AttrDw ( AttrDw ),
.Variant ( 1 ) // input-only
) i_rst_pad (
.inout_io ( rst_n ),
.in_o ( rst_no ),
.ie_i ( 1'b1 ),
.out_i ( 1'b0 ),
.oe_i ( 1'b0 ),
.attr_i ( '0 ),
.warl_o ( )
);
//////////////
// MIO Pads //
//////////////
for (genvar k = 0; k < NMioPads; k++) begin : gen_mio_pads
if (ConnectMioIn[k] && ConnectMioOut[k]) begin : gen_mio_inout
prim_pad_wrapper #(
.AttrDw ( AttrDw ),
.Variant ( MioPadVariant[k] )
) i_mio_pad (
.inout_io ( mio_pad_io[k] ),
.in_o ( mio_in_o[k] ),
.ie_i ( 1'b1 ),
.out_i ( mio_out_i[k] ),
.oe_i ( mio_oe_i[k] ),
.attr_i ( mio_attr_i[k] ),
.warl_o ( )
);
end else if (ConnectMioOut[k]) begin : gen_mio_output
prim_pad_wrapper #(
.AttrDw ( AttrDw ),
.Variant ( MioPadVariant[k] )
) i_mio_pad (
.inout_io ( mio_pad_io[k] ),
.in_o ( ),
.ie_i ( 1'b0 ),
.out_i ( mio_out_i[k] ),
.oe_i ( mio_oe_i[k] ),
.attr_i ( mio_attr_i[k] ),
.warl_o ( )
);
assign mio_in_o[k] = 1'b0;
end else if (ConnectMioIn[k]) begin : gen_mio_input
prim_pad_wrapper #(
.AttrDw ( AttrDw ),
.Variant ( MioPadVariant[k] )
) i_mio_pad (
.inout_io ( mio_pad_io[k] ),
.in_o ( mio_in_o[k] ),
.ie_i ( 1'b1 ),
.out_i ( 1'b0 ),
.oe_i ( 1'b0 ),
.attr_i ( mio_attr_i[k] ),
.warl_o ( )
);
logic unused_out, unused_oe;
assign unused_out = mio_out_i[k];
assign unused_oe = mio_oe_i[k];
end else begin : gen_mio_tie_off
logic unused_out, unused_oe, unused_pad;
logic [AttrDw-1:0] unused_attr;
assign mio_pad_io[k] = 1'b0;
assign unused_pad = mio_pad_io[k];
assign unused_out = mio_out_i[k];
assign unused_oe = mio_oe_i[k];
assign unused_attr = mio_attr_i[k];
assign mio_in_o[k] = 1'b0;
end
end
//////////////
// DIO Pads //
//////////////
for (genvar k = 0; k < NDioPads; k++) begin : gen_dio_pads
if (ConnectDioIn[k] && ConnectDioOut[k]) begin : gen_dio_inout
prim_pad_wrapper #(
.AttrDw ( AttrDw ),
.Variant ( DioPadVariant[k] )
) i_dio_pad (
.inout_io ( dio_pad_io[k] ),
.in_o ( dio_in_o[k] ),
.ie_i ( 1'b1 ),
.out_i ( dio_out_i[k] ),
.oe_i ( dio_oe_i[k] ),
.attr_i ( dio_attr_i[k] ),
.warl_o ( )
);
end else if (ConnectDioOut[k]) begin : gen_dio_output
prim_pad_wrapper #(
.AttrDw ( AttrDw ),
.Variant ( DioPadVariant[k] )
) i_dio_pad (
.inout_io ( dio_pad_io[k] ),
.in_o ( ),
.ie_i ( 1'b0 ),
.out_i ( dio_out_i[k] ),
.oe_i ( dio_oe_i[k] ),
.attr_i ( dio_attr_i[k] ),
.warl_o ( )
);
assign dio_in_o[k] = 1'b0;
end else if (ConnectDioIn[k]) begin : gen_dio_input
prim_pad_wrapper #(
.AttrDw ( AttrDw ),
.Variant ( DioPadVariant[k] )
) i_dio_pad (
.inout_io ( dio_pad_io[k] ),
.in_o ( dio_in_o[k] ),
.ie_i ( 1'b1 ),
.out_i ( 1'b0 ),
.oe_i ( 1'b0 ),
.attr_i ( dio_attr_i[k] ),
.warl_o ( )
);
logic unused_out, unused_oe;
assign unused_out = dio_out_i[k];
assign unused_oe = dio_oe_i[k];
end else begin : gen_dio_tie_off
logic unused_out, unused_oe, unused_pad;
logic [AttrDw-1:0] unused_attr;
assign dio_pad_io[k] = 1'b0;
assign unused_pad = dio_pad_io[k];
assign unused_out = dio_out_i[k];
assign unused_oe = dio_oe_i[k];
assign unused_attr = dio_attr_i[k];
assign dio_in_o[k] = 1'b0;
end
end
endmodule : padring