Skip to content

Commit

Permalink
[adc_ctrl] Updates to LP -> NP transition
Browse files Browse the repository at this point in the history
Signed-off-by: Michael Schaffner <[email protected]>
  • Loading branch information
msfschaffner committed Mar 8, 2024
1 parent 6e9adc5 commit a8ba853
Show file tree
Hide file tree
Showing 22 changed files with 172 additions and 159 deletions.
5 changes: 3 additions & 2 deletions hw/ip/adc_ctrl/data/adc_ctrl.hjson
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,9 @@
}
],
interrupt_list: [
{ name: "match_done",
desc: "ADC match or measurement event done",
{ name: "match_pending",
desc: "ADC match or measurement event has occurred",
type: "status"
}
],
alert_list: [
Expand Down
6 changes: 3 additions & 3 deletions hw/ip/adc_ctrl/doc/interfaces.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ Referring to the [Comportable guideline for peripheral device functionality](htt

## Interrupts

| Interrupt Name | Type | Description |
|:-----------------|:-------|:------------------------------------|
| match_done | Event | ADC match or measurement event done |
| Interrupt Name | Type | Description |
|:-----------------|:-------|:--------------------------------------------|
| match_pending | Status | ADC match or measurement event has occurred |

## Security Alerts

Expand Down
30 changes: 15 additions & 15 deletions hw/ip/adc_ctrl/doc/registers.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,13 @@ Interrupt State Register
### Fields

```wavejson
{"reg": [{"name": "match_done", "bits": 1, "attr": ["rw1c"], "rotate": -90}, {"bits": 31}], "config": {"lanes": 1, "fontsize": 10, "vspace": 120}}
{"reg": [{"name": "match_pending", "bits": 1, "attr": ["ro"], "rotate": -90}, {"bits": 31}], "config": {"lanes": 1, "fontsize": 10, "vspace": 150}}
```

| Bits | Type | Reset | Name | Description |
|:------:|:------:|:-------:|:-----------|:------------------------------------|
| 31:1 | | | | Reserved |
| 0 | rw1c | 0x0 | match_done | ADC match or measurement event done |
| Bits | Type | Reset | Name | Description |
|:------:|:------:|:-------:|:--------------|:--------------------------------------------|
| 31:1 | | | | Reserved |
| 0 | ro | 0x0 | match_pending | ADC match or measurement event has occurred |

## INTR_ENABLE
Interrupt Enable Register
Expand All @@ -64,13 +64,13 @@ Interrupt Enable Register
### Fields

```wavejson
{"reg": [{"name": "match_done", "bits": 1, "attr": ["rw"], "rotate": -90}, {"bits": 31}], "config": {"lanes": 1, "fontsize": 10, "vspace": 120}}
{"reg": [{"name": "match_pending", "bits": 1, "attr": ["rw"], "rotate": -90}, {"bits": 31}], "config": {"lanes": 1, "fontsize": 10, "vspace": 150}}
```

| Bits | Type | Reset | Name | Description |
|:------:|:------:|:-------:|:-----------|:---------------------------------------------------------------------|
| 31:1 | | | | Reserved |
| 0 | rw | 0x0 | match_done | Enable interrupt when [`INTR_STATE.match_done`](#intr_state) is set. |
| Bits | Type | Reset | Name | Description |
|:------:|:------:|:-------:|:--------------|:------------------------------------------------------------------------|
| 31:1 | | | | Reserved |
| 0 | rw | 0x0 | match_pending | Enable interrupt when [`INTR_STATE.match_pending`](#intr_state) is set. |

## INTR_TEST
Interrupt Test Register
Expand All @@ -81,13 +81,13 @@ Interrupt Test Register
### Fields

```wavejson
{"reg": [{"name": "match_done", "bits": 1, "attr": ["wo"], "rotate": -90}, {"bits": 31}], "config": {"lanes": 1, "fontsize": 10, "vspace": 120}}
{"reg": [{"name": "match_pending", "bits": 1, "attr": ["wo"], "rotate": -90}, {"bits": 31}], "config": {"lanes": 1, "fontsize": 10, "vspace": 150}}
```

| Bits | Type | Reset | Name | Description |
|:------:|:------:|:-------:|:-----------|:--------------------------------------------------------------|
| 31:1 | | | | Reserved |
| 0 | wo | 0x0 | match_done | Write 1 to force [`INTR_STATE.match_done`](#intr_state) to 1. |
| Bits | Type | Reset | Name | Description |
|:------:|:------:|:-------:|:--------------|:-----------------------------------------------------------------|
| 31:1 | | | | Reserved |
| 0 | wo | 0x0 | match_pending | Write 1 to force [`INTR_STATE.match_pending`](#intr_state) to 1. |

## ALERT_TEST
Alert Test Register
Expand Down
46 changes: 19 additions & 27 deletions hw/ip/adc_ctrl/dv/env/adc_ctrl_scoreboard.sv
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,12 @@ class adc_ctrl_scoreboard extends cip_base_scoreboard #(
protected bit m_debounced;
// Expected adc_intr_status (1 bit per filter + transition IRQ + oneshot mode)
protected bit [ADC_CTRL_NUM_FILTERS + 1 : 0] m_expected_adc_intr_status;
// Expected intr_state register
protected bit m_expected_intr_state;
// Expected intr_test register
protected bit m_expected_intr_test;
// Write to filter_status
protected event m_filter_status_wr_ev;
// Write to adc_intr_status
protected event m_adc_intr_status_wr_ev;
// Write to intr_state
protected event m_intr_state_wr_ev;
// Expected wakeup line
protected bit m_expected_wakeup;
// Write to adc_fsm_reset
Expand All @@ -57,7 +55,7 @@ class adc_ctrl_scoreboard extends cip_base_scoreboard #(
// Whether the FSM transitioned from LP to NP mode.
protected bit m_lp_to_np_transition = 0;
// Debug cable index in interupt registers
protected int unsigned m_match_done_index;
protected int unsigned m_match_pending_index;

`uvm_component_utils(adc_ctrl_scoreboard)

Expand All @@ -80,7 +78,7 @@ class adc_ctrl_scoreboard extends cip_base_scoreboard #(

function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
m_match_done_index = cfg.ral.intr_state.match_done.get_lsb_pos();
m_match_pending_index = cfg.ral.intr_state.match_pending.get_lsb_pos();
endfunction

task run_phase(uvm_phase phase);
Expand Down Expand Up @@ -110,11 +108,12 @@ class adc_ctrl_scoreboard extends cip_base_scoreboard #(
m_interrupt = cfg.intr_vif.sample_pin(ADC_CTRL_INTERRUPT_INDEX);
// Compare against expected every change of interrupt line
if (cfg.en_scb) begin
intr_en = ral.intr_enable.match_done.get_mirrored_value();
intr_en = ral.intr_enable.match_pending.get_mirrored_value();
`uvm_info(`gfn, $sformatf(
"monitor_intr_proc: interrupt pin change m_interrupt=%b", m_interrupt),
UVM_MEDIUM)
`DV_CHECK_EQ(m_interrupt, (m_expected_intr_state & intr_en))
`DV_CHECK_EQ(m_interrupt,
((m_expected_intr_test || |m_expected_adc_intr_status) && intr_en))
if (cfg.en_cov) begin
// Sample interrupt pin coverage for interrupt pins
cov.intr_pins_cg.sample(ADC_CTRL_INTERRUPT_INDEX, m_interrupt);
Expand Down Expand Up @@ -227,30 +226,26 @@ class adc_ctrl_scoreboard extends cip_base_scoreboard #(
case (csr.get_name())
// add individual case item for each csr
"intr_state": begin
bit intr_en = ral.intr_enable.match_done.get_mirrored_value();
bit intr_en = ral.intr_enable.match_pending.get_mirrored_value();
do_read_check = 1;
if (addr_phase_write) begin
->m_intr_state_wr_ev;
// Implement W1C
m_expected_intr_state &= !get_field_val(cfg.ral.intr_state.match_done, item.a_data);
end
if (addr_phase_read) begin
`DV_CHECK(csr.predict(.value(m_expected_intr_state), .kind(UVM_PREDICT_READ)))
`DV_CHECK(csr.predict(.value(m_expected_intr_test || |m_expected_adc_intr_status),
.kind(UVM_PREDICT_READ)))
end
if (cfg.en_cov && data_phase_read) begin
cov.intr_cg.sample(m_match_done_index, intr_en, get_field_val(
cfg.ral.intr_state.match_done, item.a_data));
cov.intr_cg.sample(m_match_pending_index, intr_en, get_field_val(
cfg.ral.intr_state.match_pending, item.a_data));
end
end
"intr_test": begin
// Model intr_test functionality
bit intr_test_val = get_field_val(cfg.ral.intr_test.match_done, item.a_data);
bit intr_en = ral.intr_enable.match_done.get_mirrored_value();
bit intr_test_val = get_field_val(cfg.ral.intr_test.match_pending, item.a_data);
bit intr_en = ral.intr_enable.match_pending.get_mirrored_value();
if (addr_phase_write) begin
m_expected_intr_state |= intr_test_val;
m_expected_intr_test = intr_test_val;
if (cfg.en_cov) begin
cov.intr_test_cg.sample(m_match_done_index, intr_test_val, intr_en,
m_expected_intr_state);
cov.intr_test_cg.sample(m_match_pending_index, intr_test_val, intr_en,
m_expected_intr_test || |m_expected_adc_intr_status);
end
end
end
Expand Down Expand Up @@ -532,7 +527,6 @@ class adc_ctrl_scoreboard extends cip_base_scoreboard #(
// One hot interrupt is one bit above the transition interrupt
if (cfg.testmode inside {AdcCtrlTestmodeOneShot}) begin
m_expected_adc_intr_status[ADC_CTRL_NUM_FILTERS+1] = cfg.adc_intr_ctl[ADC_CTRL_NUM_FILTERS+1];
m_expected_intr_state |= cfg.adc_intr_ctl[ADC_CTRL_NUM_FILTERS+1];
end

// Delay for edge detection
Expand Down Expand Up @@ -561,8 +555,7 @@ class adc_ctrl_scoreboard extends cip_base_scoreboard #(
// Capture matches
m_debounced = 1;
m_expected_filter_status |= m_match;
m_expected_adc_intr_status |= m_match & cfg.adc_intr_ctl;
m_expected_intr_state |= (|(m_match & cfg.adc_intr_ctl));
m_expected_adc_intr_status |= m_match & cfg.adc_intr_ctl[ADC_CTRL_NUM_FILTERS-1:0];

// Update interrupt ADC values
foreach (m_adc_latest_values[channel]) begin
Expand Down Expand Up @@ -620,7 +613,6 @@ class adc_ctrl_scoreboard extends cip_base_scoreboard #(
// The associated interrupt is located one bit above the last filter index.
m_expected_adc_intr_status[ADC_CTRL_NUM_FILTERS] |=
cfg.adc_intr_ctl[ADC_CTRL_NUM_FILTERS];
m_expected_intr_state |= cfg.adc_intr_ctl[ADC_CTRL_NUM_FILTERS];
// Decode expected wakeup - allow dynamic control
m_expected_wakeup |= cfg.ral.adc_wakeup_ctl.trans_en.get_mirrored_value();
m_lp_counter = 0;
Expand Down Expand Up @@ -652,7 +644,7 @@ class adc_ctrl_scoreboard extends cip_base_scoreboard #(
m_debounced = 0;
m_expected_filter_status = 0;
m_expected_adc_intr_status = 0;
m_expected_intr_state = 0;
m_expected_intr_test = 0;
m_adc_ctrl_en = 0;
m_lp_mode = 0;
m_lp_to_np_transition = 0;
Expand Down
24 changes: 12 additions & 12 deletions hw/ip/adc_ctrl/dv/tb.sv
Original file line number Diff line number Diff line change
Expand Up @@ -88,18 +88,18 @@ module tb;

// dut
adc_ctrl dut (
.clk_i (clk),
.rst_ni (rst_n),
.clk_aon_i (clk_aon),
.rst_aon_ni (rst_aon_n),
.tl_i (tl_if.h2d),
.tl_o (tl_if.d2h),
.alert_rx_i (alert_rx),
.alert_tx_o (alert_tx),
.adc_o (adc_o),
.adc_i (adc_i),
.intr_match_done_o (interrupts[ADC_CTRL_INTERRUPT_INDEX]),
.wkup_req_o (wakeup_req)
.clk_i (clk),
.rst_ni (rst_n),
.clk_aon_i (clk_aon),
.rst_aon_ni (rst_aon_n),
.tl_i (tl_if.h2d),
.tl_o (tl_if.d2h),
.alert_rx_i (alert_rx),
.alert_tx_o (alert_tx),
.adc_o (adc_o),
.adc_i (adc_i),
.intr_match_pending_o (interrupts[ADC_CTRL_INTERRUPT_INDEX]),
.wkup_req_o (wakeup_req)
);

initial begin
Expand Down
6 changes: 3 additions & 3 deletions hw/ip/adc_ctrl/rtl/adc_ctrl.sv
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ module adc_ctrl
input ast_pkg::adc_ast_rsp_t adc_i,

// Interrupt indicates a matching or measurement is done
output logic intr_match_done_o,
output logic intr_match_pending_o,

// Pwrmgr interface
// Debug cable is detected; wake up the chip in normal sleep and deep sleep mode
Expand Down Expand Up @@ -90,14 +90,14 @@ module adc_ctrl
.adc_intr_status_o(hw2reg.adc_intr_status),
.aon_filter_status_o(hw2reg.filter_status),
.wkup_req_o,
.intr_o(intr_match_done_o),
.intr_o(intr_match_pending_o),
.adc_i(adc_i),
.adc_o(adc_o),
.aon_fsm_state_o(hw2reg.adc_fsm_state.d)
);

// All outputs should be known value after reset
`ASSERT_KNOWN(IntrKnown, intr_match_done_o)
`ASSERT_KNOWN(IntrKnown, intr_match_pending_o)
`ASSERT_KNOWN(WakeKnown, wkup_req_o)
`ASSERT_KNOWN(TlODValidKnown, tl_o.d_valid)
`ASSERT_KNOWN(TlOAReadyKnown, tl_o.a_ready)
Expand Down
39 changes: 19 additions & 20 deletions hw/ip/adc_ctrl/rtl/adc_ctrl_intr.sv
Original file line number Diff line number Diff line change
Expand Up @@ -89,36 +89,35 @@ module adc_ctrl_intr
.dst_ack_i(dst_ack)
);

// To write into interrupt status register. Note that we're also adding the non-AON interrupt
// source cfg_oneshot_done_i at this point.
logic [1+NumAonIntrEvents-1:0] intr_events;

// Note that aon_req_hold is a value held in an async domain.
// aon_req_hold's value should not change until handshake is completed by `prim_sync_reqack`.
// There is no reason to use `prim_sync_reqack` in this case because that module passes
// through data only when the direction is src->dst.
assign intr_events = {cfg_oneshot_done_i, {NumAonIntrEvents{dst_ack}} & aon_req_hold_q} &
{cfg_oneshot_done_en_i, cfg_intr_trans_en_i, cfg_intr_en_i};

assign adc_intr_status_o.match.de = |intr_events[7:0];
assign adc_intr_status_o.trans.de = intr_events[8];
assign adc_intr_status_o.oneshot.de = intr_events[9];

// since interrupt events are pulsed, when successive events arrive we need to make sure to
// hold the previously latched values
assign adc_intr_status_o.match.d = intr_events[7:0] | adc_intr_status_i.match.q;

logic unused_sigs;
assign unused_sigs = ^{adc_intr_status_i.oneshot.q,
adc_intr_status_i.trans.q};
assign adc_intr_status_o.trans.de = cfg_intr_trans_en_i && dst_ack && aon_req_hold_q[8];
assign adc_intr_status_o.trans.d = 1'b1;
// Since interrupt events are pulsed, when successive events arrive we need to make sure to
// hold the previously latched values
logic [NumAdcFilter-1:0] match_events;
assign match_events = cfg_intr_en_i & {NumAdcFilter{dst_ack}} & aon_req_hold_q[NumAdcFilter-1:0];
assign adc_intr_status_o.match.de = |match_events;
assign adc_intr_status_o.match.d = match_events | adc_intr_status_i.match.q;
// Note that we're also adding the non-AON interrupt source cfg_oneshot_done_i at this point.
assign adc_intr_status_o.oneshot.de = cfg_oneshot_done_i && cfg_oneshot_done_en_i;
assign adc_intr_status_o.oneshot.d = 1'b1;

logic status_irq_value;
assign status_irq_value = |{adc_intr_status_i.oneshot.q,
adc_intr_status_i.trans.q,
adc_intr_status_i.match.q};

// instantiate interrupt hardware primitive
prim_intr_hw #(.Width(1)) i_adc_ctrl_intr_o (
prim_intr_hw #(
.Width(1),
.IntrT("Status")
) i_adc_ctrl_intr_o (
.clk_i(clk_i),
.rst_ni(rst_ni),
.event_intr_i (|intr_events),
.event_intr_i (status_irq_value),
.reg2hw_intr_enable_q_i (intr_enable_i.q),
.reg2hw_intr_test_q_i (intr_test_i.q),
.reg2hw_intr_test_qe_i (intr_test_i.qe),
Expand Down
2 changes: 1 addition & 1 deletion hw/ip/adc_ctrl/rtl/adc_ctrl_reg_pkg.sv
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,7 @@ package adc_ctrl_reg_pkg;

// Reset values for hwext registers and their fields
parameter logic [0:0] ADC_CTRL_INTR_TEST_RESVAL = 1'h 0;
parameter logic [0:0] ADC_CTRL_INTR_TEST_MATCH_DONE_RESVAL = 1'h 0;
parameter logic [0:0] ADC_CTRL_INTR_TEST_MATCH_PENDING_RESVAL = 1'h 0;
parameter logic [0:0] ADC_CTRL_ALERT_TEST_RESVAL = 1'h 0;
parameter logic [0:0] ADC_CTRL_ALERT_TEST_FATAL_FAULT_RESVAL = 1'h 0;
parameter logic [4:0] ADC_CTRL_ADC_FSM_STATE_RESVAL = 5'h 0;
Expand Down
13 changes: 4 additions & 9 deletions hw/ip/adc_ctrl/rtl/adc_ctrl_reg_top.sv
Original file line number Diff line number Diff line change
Expand Up @@ -123,9 +123,7 @@ module adc_ctrl_reg_top (
// Define SW related signals
// Format: <reg>_<field>_{wd|we|qs}
// or <reg>_{wd|we|qs} if field == 1 or 0
logic intr_state_we;
logic intr_state_qs;
logic intr_state_wd;
logic intr_enable_we;
logic intr_enable_qs;
logic intr_enable_wd;
Expand Down Expand Up @@ -1356,16 +1354,16 @@ module adc_ctrl_reg_top (
// R[intr_state]: V(False)
prim_subreg #(
.DW (1),
.SwAccess(prim_subreg_pkg::SwAccessW1C),
.SwAccess(prim_subreg_pkg::SwAccessRO),
.RESVAL (1'h0),
.Mubi (1'b0)
) u_intr_state (
.clk_i (clk_i),
.rst_ni (rst_ni),

// from register interface
.we (intr_state_we),
.wd (intr_state_wd),
.we (1'b0),
.wd ('0),

// from internal hardware
.de (hw2reg.intr_state.de),
Expand Down Expand Up @@ -4050,9 +4048,6 @@ module adc_ctrl_reg_top (
end

// Generate write-enables
assign intr_state_we = addr_hit[0] & reg_we & !reg_error;

assign intr_state_wd = reg_wdata[0];
assign intr_enable_we = addr_hit[1] & reg_we & !reg_error;

assign intr_enable_wd = reg_wdata[0];
Expand Down Expand Up @@ -4180,7 +4175,7 @@ module adc_ctrl_reg_top (
// Assign write-enables to checker logic vector.
always_comb begin
reg_we_check = '0;
reg_we_check[0] = intr_state_we;
reg_we_check[0] = 1'b0;
reg_we_check[1] = intr_enable_we;
reg_we_check[2] = intr_test_we;
reg_we_check[3] = alert_test_we;
Expand Down
4 changes: 2 additions & 2 deletions hw/top_earlgrey/data/autogen/top_earlgrey.gen.hjson
Original file line number Diff line number Diff line change
Expand Up @@ -14287,11 +14287,11 @@
default_val: false
}
{
name: adc_ctrl_aon_match_done
name: adc_ctrl_aon_match_pending
width: 1
type: interrupt
module_name: adc_ctrl_aon
intr_type: IntrType.Event
intr_type: IntrType.Status
default_val: false
}
{
Expand Down
Loading

0 comments on commit a8ba853

Please sign in to comment.