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