../src/lowrisc_ip_gpio_0.1/rtl/gpio.sv Cov: 100%
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: // General Purpose Input/Output module
6:
7: `include "prim_assert.sv"
8:
9: module gpio (
10: input clk_i,
11: input rst_ni,
12:
13: // Below Regster interface can be changed
14: input tlul_pkg::tl_h2d_t tl_i,
15: output tlul_pkg::tl_d2h_t tl_o,
16:
17: input [31:0] cio_gpio_i,
18: output logic [31:0] cio_gpio_o,
19: output logic [31:0] cio_gpio_en_o,
20:
21: output logic [31:0] intr_gpio_o
22: );
23:
24: import gpio_reg_pkg::* ;
25:
26: gpio_reg2hw_t reg2hw;
27: gpio_hw2reg_t hw2reg;
28:
29: logic [31:0] cio_gpio_q;
30: logic [31:0] cio_gpio_en_q;
31:
32: // possibly filter the input based upon register configuration
33:
34: logic [31:0] data_in_d;
35:
36: for (genvar i = 0 ; i < 32 ; i++) begin : gen_filter
37: prim_filter_ctr #(.Cycles(16)) filter (
38: .clk_i,
39: .rst_ni,
40: .enable_i(reg2hw.ctrl_en_input_filter.q[i]),
41: .filter_i(cio_gpio_i[i]),
42: .filter_o(data_in_d[i])
43: );
44: end
45:
46: // GPIO_IN
47: assign hw2reg.data_in.de = 1'b1;
48: assign hw2reg.data_in.d = data_in_d;
49:
50: // GPIO_OUT
51: assign cio_gpio_o = cio_gpio_q;
52: assign cio_gpio_en_o = cio_gpio_en_q;
53:
54: assign hw2reg.direct_out.d = cio_gpio_q;
55: assign hw2reg.masked_out_upper.data.d = cio_gpio_q[31:16];
56: assign hw2reg.masked_out_upper.mask.d = 16'h 0;
57: assign hw2reg.masked_out_lower.data.d = cio_gpio_q[15:0];
58: assign hw2reg.masked_out_lower.mask.d = 16'h 0;
59:
60: always_ff @(posedge clk_i or negedge rst_ni) begin
61: if (!rst_ni) begin
62: cio_gpio_q <= '0;
63: end else if (reg2hw.direct_out.qe) begin
64: cio_gpio_q <= reg2hw.direct_out.q;
65: end else if (reg2hw.masked_out_upper.data.qe) begin
66: cio_gpio_q[31:16] <=
67: ( reg2hw.masked_out_upper.mask.q & reg2hw.masked_out_upper.data.q) |
68: (~reg2hw.masked_out_upper.mask.q & cio_gpio_q[31:16]);
69: end else if (reg2hw.masked_out_lower.data.qe) begin
70: cio_gpio_q[15:0] <=
71: ( reg2hw.masked_out_lower.mask.q & reg2hw.masked_out_lower.data.q) |
72: (~reg2hw.masked_out_lower.mask.q & cio_gpio_q[15:0]);
73: end
74: end
75:
76: // GPIO OE
77: assign hw2reg.direct_oe.d = cio_gpio_en_q;
78: assign hw2reg.masked_oe_upper.data.d = cio_gpio_en_q[31:16];
79: assign hw2reg.masked_oe_upper.mask.d = 16'h 0;
80: assign hw2reg.masked_oe_lower.data.d = cio_gpio_en_q[15:0];
81: assign hw2reg.masked_oe_lower.mask.d = 16'h 0;
82:
83: always_ff @(posedge clk_i or negedge rst_ni) begin
84: if (!rst_ni) begin
85: cio_gpio_en_q <= '0;
86: end else if (reg2hw.direct_oe.qe) begin
87: cio_gpio_en_q <= reg2hw.direct_oe.q;
88: end else if (reg2hw.masked_oe_upper.data.qe) begin
89: cio_gpio_en_q[31:16] <=
90: ( reg2hw.masked_oe_upper.mask.q & reg2hw.masked_oe_upper.data.q) |
91: (~reg2hw.masked_oe_upper.mask.q & cio_gpio_en_q[31:16]);
92: end else if (reg2hw.masked_oe_lower.data.qe) begin
93: cio_gpio_en_q[15:0] <=
94: ( reg2hw.masked_oe_lower.mask.q & reg2hw.masked_oe_lower.data.q) |
95: (~reg2hw.masked_oe_lower.mask.q & cio_gpio_en_q[15:0]);
96: end
97: end
98:
99: logic [31:0] data_in_q;
100: always_ff @(posedge clk_i) begin
101: data_in_q <= data_in_d;
102: end
103:
104: logic [31:0] event_intr_rise, event_intr_fall, event_intr_actlow, event_intr_acthigh;
105: logic [31:0] event_intr_combined;
106:
107: // instantiate interrupt hardware primitive
108: prim_intr_hw #(.Width(32)) intr_hw (
109: .event_intr_i (event_intr_combined),
110: .reg2hw_intr_enable_q_i (reg2hw.intr_enable.q),
111: .reg2hw_intr_test_q_i (reg2hw.intr_test.q),
112: .reg2hw_intr_test_qe_i (reg2hw.intr_test.qe),
113: .reg2hw_intr_state_q_i (reg2hw.intr_state.q),
114: .hw2reg_intr_state_de_o (hw2reg.intr_state.de),
115: .hw2reg_intr_state_d_o (hw2reg.intr_state.d),
116: .intr_o (intr_gpio_o)
117: );
118:
119: // detect four possible individual interrupts
120: assign event_intr_rise = (~data_in_q & data_in_d) & reg2hw.intr_ctrl_en_rising.q;
121: assign event_intr_fall = ( data_in_q & ~data_in_d) & reg2hw.intr_ctrl_en_falling.q;
122: assign event_intr_acthigh = data_in_d & reg2hw.intr_ctrl_en_lvlhigh.q;
123: assign event_intr_actlow = ~data_in_d & reg2hw.intr_ctrl_en_lvllow.q;
124:
125: assign event_intr_combined = event_intr_rise |
126: event_intr_fall |
127: event_intr_actlow |
128: event_intr_acthigh;
129:
130:
131: // Register module
132: gpio_reg_top u_reg (
133: .clk_i,
134: .rst_ni,
135:
136: .tl_i,
137: .tl_o,
138:
139: .reg2hw,
140: .hw2reg,
141:
142: .devmode_i (1'b1)
143: );
144:
145: // Assert Known: Outputs
146: `ASSERT_KNOWN(IntrGpioKnown, intr_gpio_o)
147: `ASSERT_KNOWN(CioGpioEnOKnown, cio_gpio_en_o)
148: `ASSERT_KNOWN(CioGpioOKnown, cio_gpio_o)
149:
150: endmodule
151: