blob: 5683741f5b45739ac61e8e2f63f896eb20b4ebf4 [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 placed into the toplevel.
// It basically just wraps the regfile and outputs the configuration bits
// to be consumed on the chiplevel.
//
`include "prim_assert.sv"
module padctrl import padctrl_reg_pkg::*; (
input clk_i,
input rst_ni,
// Bus Interface (device)
input tlul_pkg::tl_h2d_t tl_i,
output tlul_pkg::tl_d2h_t tl_o,
// pad attributes to chip level instance
output logic[NMioPads-1:0][AttrDw-1:0] mio_attr_o,
output logic[NDioPads-1:0][AttrDw-1:0] dio_attr_o
);
/////////////
// Regfile //
/////////////
padctrl_reg2hw_t reg2hw;
padctrl_hw2reg_t hw2reg;
padctrl_reg_top u_reg (
.clk_i ,
.rst_ni ,
.tl_i ,
.tl_o ,
.reg2hw ,
.hw2reg ,
.devmode_i(1'b1)
);
////////////////
// HWEXT Regs //
////////////////
logic [NDioPads-1:0][AttrDw-1:0] dio_attr_q;
logic [NMioPads-1:0][AttrDw-1:0] mio_attr_q;
always_ff @(posedge clk_i or negedge rst_ni) begin : p_regs
if (!rst_ni) begin
dio_attr_q <= '0;
mio_attr_q <= '0;
end else begin
// dedicated pads
for (int kk = 0; kk < NDioPads; kk++) begin
if (reg2hw.dio_pads[kk].qe) begin
dio_attr_q[kk] <= reg2hw.dio_pads[kk].q;
end
end
// muxed pads
for (int kk = 0; kk < NMioPads; kk++) begin
if (reg2hw.mio_pads[kk].qe) begin
mio_attr_q[kk] <= reg2hw.mio_pads[kk].q;
end
end
end
end
////////////////////////
// Connect attributes //
////////////////////////
// Note that these are not real pad instances. We only query the supported attributes here
for (genvar k = 0; k < NDioPads; k++) begin : gen_dio_attr
logic [AttrDw-1:0] warl_mask;
prim_generic_pad_wrapper #(
.AttrDw ( AttrDw ),
.WarlOnly ( 1'b1 ) // this prevents instantiation of pad logic
) i_prim_generic_pad_wrapper (
.inout_io ( ),
.in_o ( ),
.ie_i ( 1'b0 ),
.out_i ( 1'b0 ),
.oe_i ( 1'b0 ),
.attr_i ( '0 ),
.warl_o ( warl_mask )
);
assign dio_attr_o[k] = dio_attr_q[k] & warl_mask;
assign hw2reg.dio_pads[k].d = dio_attr_q[k] & warl_mask;
end
for (genvar k = 0; k < NMioPads; k++) begin : gen_mio_attr
logic [AttrDw-1:0] warl_mask;
prim_generic_pad_wrapper #(
.AttrDw ( AttrDw ),
.WarlOnly ( 1'b1 ) // this prevents instantiation of pad logic
) i_prim_generic_pad_wrapper (
.inout_io ( ),
.in_o ( ),
.ie_i ( 1'b0 ),
.out_i ( 1'b0 ),
.oe_i ( 1'b0 ),
.attr_i ( '0 ),
.warl_o ( warl_mask )
);
assign mio_attr_o[k] = mio_attr_q[k] & warl_mask;
assign hw2reg.mio_pads[k].d = mio_attr_q[k] & warl_mask;
end
////////////////
// Assertions //
////////////////
`ASSERT_KNOWN(TlDValidKnownO_A, tl_o.d_valid)
`ASSERT_KNOWN(TlAReadyKnownO_A, tl_o.a_ready)
`ASSERT_KNOWN(MioKnownO_A, mio_attr_o)
`ASSERT_KNOWN(DioKnownO_A, dio_attr_o)
endmodule : padctrl