../src/lowrisc_ip_padctrl_component_0.1/rtl/padctrl.sv Cov: 91.1%
1: // Copyright lowRISC contributors.
2: // Licensed under the Apache License, Version 2.0, see LICENSE for details.
3: // SPDX-License-Identifier: Apache-2.0
4: //
5: // This it the padctrl portion that has to be placed into the toplevel.
6: // It basically just wraps the regfile and outputs the configuration bits
7: // to be consumed on the chiplevel.
8: //
9:
10: `include "prim_assert.sv"
11:
12: `ifndef PRIM_DEFAULT_IMPL
13: `define PRIM_DEFAULT_IMPL prim_pkg::ImplGeneric
14: `endif
15:
16: module padctrl import padctrl_reg_pkg::*; #(
17: parameter prim_pkg::impl_e Impl = `PRIM_DEFAULT_IMPL
18: ) (
19: input clk_i,
20: input rst_ni,
21: // Bus Interface (device)
22: input tlul_pkg::tl_h2d_t tl_i,
23: output tlul_pkg::tl_d2h_t tl_o,
24: // pad attributes to chip level instance
25: output logic[NMioPads-1:0][AttrDw-1:0] mio_attr_o,
26: output logic[NDioPads-1:0][AttrDw-1:0] dio_attr_o
27: );
28:
29: //////////////////
30: // WARL Control //
31: //////////////////
32:
33: // This controls the WARL'ness of the CSRs
34: // needs to be in line with the corresponding
35: // prim_pad_wrapper implementation
36: logic [AttrDw-1:0] warl_mask;
37: if (Impl == prim_pkg::ImplGeneric) begin : gen_generic
38: // all attributes supported
39: assign warl_mask = AttrDw'(6'h3F);
40: end else if (Impl == prim_pkg::ImplXilinx) begin : gen_xilinx
41: // only OD and INV supported
42: assign warl_mask = AttrDw'(2'h3);
43: end else begin : gen_others
44: // all attributes supported
45: assign warl_mask = AttrDw'(6'h3F);
46: end
47:
48: /////////////
49: // Regfile //
50: /////////////
51:
52: padctrl_reg2hw_t reg2hw;
53: padctrl_hw2reg_t hw2reg;
54:
55: padctrl_reg_top i_reg_top (
56: .clk_i ,
57: .rst_ni ,
58: .tl_i ,
59: .tl_o ,
60: .reg2hw ,
61: .hw2reg ,
62: .devmode_i(1'b1)
63: );
64:
65: ////////////////
66: // HWEXT Regs //
67: ////////////////
68:
69: logic [NDioPads-1:0][AttrDw-1:0] dio_attr_q;
70: logic [NMioPads-1:0][AttrDw-1:0] mio_attr_q;
71:
72: always_ff @(posedge clk_i or negedge rst_ni) begin : p_regs
73: if (!rst_ni) begin
74: dio_attr_q <= '0;
75: mio_attr_q <= '0;
76: end else begin
77: // dedicated pads
78: for (int kk = 0; kk < NDioPads; kk++) begin
79: if (reg2hw.dio_pads[kk].qe) begin
80: dio_attr_q[kk] <= reg2hw.dio_pads[kk].q;
81: end
82: end
83: // muxed pads
84: for (int kk = 0; kk < NMioPads; kk++) begin
85: if (reg2hw.mio_pads[kk].qe) begin
86: mio_attr_q[kk] <= reg2hw.mio_pads[kk].q;
87: end
88: end
89: end
90: end
91:
92: ////////////////////////
93: // Connect attributes //
94: ////////////////////////
95:
96: // using the warl_mask here instead instead of in the register assignment above
97: // avoids lint errors. the unused registers can be removed automatically by most tools.
98: for (genvar k = 0; k < NDioPads; k++) begin : gen_dio_attr
99: assign dio_attr_o[k] = dio_attr_q[k] & warl_mask;
100: assign hw2reg.dio_pads[k].d = dio_attr_q[k] & warl_mask;
101: end
102:
103: for (genvar k = 0; k < NMioPads; k++) begin : gen_mio_attr
104: assign mio_attr_o[k] = mio_attr_q[k] & warl_mask;
105: assign hw2reg.mio_pads[k].d = mio_attr_q[k] & warl_mask;
106: end
107:
108: ////////////////
109: // Assertions //
110: ////////////////
111:
112: `ASSERT_KNOWN(TlDValidKnownO_A, tl_o.d_valid)
113: `ASSERT_KNOWN(TlAReadyKnownO_A, tl_o.a_ready)
114: `ASSERT_KNOWN(MioKnownO_A, mio_attr_o)
115: `ASSERT_KNOWN(DioKnownO_A, dio_attr_o)
116:
117: endmodule : padctrl
118: