hw/ip/rv_timer/rtl/rv_timer.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:
6:
7: module rv_timer (
8: input clk_i,
9: input rst_ni,
10:
11: input tlul_pkg::tl_h2d_t tl_i,
12: output tlul_pkg::tl_d2h_t tl_o,
13:
14: output logic intr_timer_expired_0_0_o
15: );
16:
17: localparam int N_HARTS = 1;
18: localparam int N_TIMERS = 1;
19:
20: import rv_timer_reg_pkg::*;
21:
22: rv_timer_reg2hw_t reg2hw;
23: rv_timer_hw2reg_t hw2reg;
24:
25: logic [N_HARTS-1:0] active;
26:
27: logic [11:0] prescaler [N_HARTS];
28: logic [7:0] step [N_HARTS];
29:
30: logic [N_HARTS-1:0] tick;
31:
32: logic [63:0] mtime_d [N_HARTS];
33: logic [63:0] mtime [N_HARTS];
34: logic [63:0] mtimecmp [N_HARTS][N_TIMERS]; // Only [harts][0] is connected to mtimecmp CSRs
35:
36: logic [N_HARTS*N_TIMERS-1:0] intr_timer_set;
37: logic [N_HARTS*N_TIMERS-1:0] intr_timer_en;
38: logic [N_HARTS*N_TIMERS-1:0] intr_timer_test_q;
39: logic [N_HARTS-1:0] intr_timer_test_qe;
40: logic [N_HARTS*N_TIMERS-1:0] intr_timer_state_q;
41: logic [N_HARTS-1:0] intr_timer_state_de;
42: logic [N_HARTS*N_TIMERS-1:0] intr_timer_state_d;
43:
44: logic [N_HARTS*N_TIMERS-1:0] intr_out;
45:
46: /////////////////////////////////////////////////
47: // Connecting register interface to the signal //
48: /////////////////////////////////////////////////
49:
50: // Once reggen supports nested multireg, the following can be automated. For the moment, it must
51: // be connected manually.
52: assign active[0] = reg2hw.ctrl[0].q;
53: assign prescaler = '{reg2hw.cfg0.prescale.q};
54: assign step = '{reg2hw.cfg0.step.q};
55:
56: assign hw2reg.timer_v_upper0.de = tick[0];
57: assign hw2reg.timer_v_lower0.de = tick[0];
58: assign hw2reg.timer_v_upper0.d = mtime_d[0][63:32];
59: assign hw2reg.timer_v_lower0.d = mtime_d[0][31: 0];
60: assign mtime[0] = {reg2hw.timer_v_upper0.q, reg2hw.timer_v_lower0.q};
61: assign mtimecmp = '{'{{reg2hw.compare_upper0_0,reg2hw.compare_lower0_0}}};
62:
63: assign intr_timer_expired_0_0_o = intr_out[0];
64: assign intr_timer_en = reg2hw.intr_enable0[0].q;
65: assign intr_timer_state_q = reg2hw.intr_state0[0].q;
66: assign intr_timer_test_q = reg2hw.intr_test0[0].q;
67: assign intr_timer_test_qe = reg2hw.intr_test0[0].qe;
68: assign hw2reg.intr_state0[0].de = intr_timer_state_de;
69: assign hw2reg.intr_state0[0].d = intr_timer_state_d;
70:
71:
72: for (genvar h = 0 ; h < N_HARTS ; h++) begin : gen_harts
73: prim_intr_hw #(
74: .Width(N_TIMERS)
75: ) u_intr_hw (
76: .event_intr_i (intr_timer_set),
77:
78: .reg2hw_intr_enable_q_i (intr_timer_en[h*N_TIMERS+:N_TIMERS]),
79: .reg2hw_intr_test_q_i (intr_timer_test_q[h*N_TIMERS+:N_TIMERS]),
80: .reg2hw_intr_test_qe_i (intr_timer_test_qe[h]),
81: .reg2hw_intr_state_q_i (intr_timer_state_q[h*N_TIMERS+:N_TIMERS]),
82: .hw2reg_intr_state_de_o (intr_timer_state_de),
83: .hw2reg_intr_state_d_o (intr_timer_state_d[h*N_TIMERS+:N_TIMERS]),
84:
85: .intr_o (intr_out[h*N_TIMERS+:N_TIMERS])
86: );
87:
88: timer_core #(
89: .N (N_TIMERS)
90: ) u_core (
91: .clk_i,
92: .rst_ni,
93:
94: .active (active[h]),
95: .prescaler (prescaler[h]),
96: .step (step[h]),
97:
98: .tick (tick[h]),
99:
100: .mtime_d (mtime_d[h]),
101: .mtime (mtime[h]),
102: .mtimecmp (mtimecmp[h]),
103:
104: .intr (intr_timer_set[h*N_TIMERS+:N_TIMERS])
105: );
106: end : gen_harts
107:
108: // Register module
109: rv_timer_reg_top u_reg (
110: .clk_i,
111: .rst_ni,
112:
113: .tl_i,
114: .tl_o,
115:
116: .reg2hw,
117: .hw2reg,
118:
119: .devmode_i (1'b1)
120: );
121:
122: ////////////////
123: // Assertions //
124: ////////////////
125: `ASSERT_KNOWN(TlODValidKnown, tl_o.d_valid, clk_i, !rst_ni)
126: `ASSERT_KNOWN(TlOAReadyKnown, tl_o.a_ready, clk_i, !rst_ni)
127: `ASSERT_KNOWN(IntrTimerExpired00Known, intr_timer_expired_0_0_o, clk_i, !rst_ni)
128:
129: endmodule
130: