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 6, 2024
1 parent a322461 commit 8ba5e97
Show file tree
Hide file tree
Showing 17 changed files with 546 additions and 194 deletions.
71 changes: 63 additions & 8 deletions hw/ip/adc_ctrl/data/adc_ctrl.hjson
Original file line number Diff line number Diff line change
Expand Up @@ -306,8 +306,29 @@
resval: "0",
fields: [
{ bits: "NumAdcFilter-1:0",
name: "EN",
desc: "0: filter match wil not generate wakeupe; 1: filter match will generate wakeup",
name: "MATCH_EN",
desc: '''
Filter wakeup source.

0: filter match will not generate wakeup;
1: filter match will generate wakeup
'''
}
{
bits: "NumAdcFilter:NumAdcFilter",
name: "TRANS_EN",
desc: '''
Wakeup due to FSM transition from low power sampling
mode to normal sampling mode.

Note that this wakeup source is primarily intended for debug purposes.
If enabled all the time, this can lead to many wakeups due to false
positives that are ruled out automatically by adc_ctrl after
transitioning from LP -> NP.

0: transition match will not generate wakeup;
1: transition match will generate wakeup
'''
}
]
}
Expand All @@ -324,9 +345,13 @@
resval: "0",
fields: [
{ bits: "7:0",
name: "COND",
name: "MATCH",
desc: "0: filter condition is not met; 1: filter condition is met",
}
{ bits: "NumAdcFilter:NumAdcFilter",
name: "TRANS",
desc: "0: transition did not occur; 1: transition occurred",
}
]
}

Expand All @@ -343,10 +368,36 @@
hwaccess: "hro",
resval: "0",
fields: [
{ bits: "8:0",
name: "EN",
desc: "0: interrupt source is not enabled; 1: interrupt source is enabled",
{ bits: "NumAdcFilter-1:0",
name: "MATCH_EN",
desc: '''
Filter interrupt source.

0: interrupt source is not enabled; 1: interrupt source is enabled
'''
}
{
bits: "NumAdcFilter:NumAdcFilter",
name: "TRANS_EN",
desc: '''
Interrupt due to FSM transition from low power sampling
mode to normal sampling mode. This is mainly intended for debug.

Note that this interrupt is primarily intended for debug purposes.

0: interrupt source is not enabled; 1: interrupt source is enabled
'''
}
{
bits: "NumAdcFilter+1:NumAdcFilter+1",
name: "ONESHOT_EN",
desc: '''
Interrupt due to oneshot sampling.

0: interrupt source is not enabled; 1: interrupt source is enabled
'''
}

]
}

Expand All @@ -360,11 +411,15 @@
"excl:CsrNonInitTests:CsrExclCheck"],
fields: [
{ bits: "NumAdcFilter-1:0",
name: "filter_match",
name: "MATCH",
desc: "0: filter condition is not met; 1: filter condition is met",
}
{ bits: "NumAdcFilter:NumAdcFilter",
name: "oneshot",
name: "TRANS",
desc: "0: transition did not occur; 1: transition occurred",
}
{ bits: "NumAdcFilter+1:NumAdcFilter+1",
name: "ONESHOT",
desc: "0: oneshot sample is not done ; 1: oneshot sample is done",
}
]
Expand Down
87 changes: 64 additions & 23 deletions hw/ip/adc_ctrl/doc/registers.md
Original file line number Diff line number Diff line change
Expand Up @@ -304,37 +304,57 @@ ADC value sampled on channel
Enable filter matches as wakeups
- Offset: `0x6c`
- Reset default: `0x0`
- Reset mask: `0xff`
- Reset mask: `0x1ff`

### Fields

```wavejson
{"reg": [{"name": "EN", "bits": 8, "attr": ["rw"], "rotate": 0}, {"bits": 24}], "config": {"lanes": 1, "fontsize": 10, "vspace": 80}}
{"reg": [{"name": "MATCH_EN", "bits": 8, "attr": ["rw"], "rotate": 0}, {"name": "TRANS_EN", "bits": 1, "attr": ["rw"], "rotate": -90}, {"bits": 23}], "config": {"lanes": 1, "fontsize": 10, "vspace": 100}}
```

| Bits | Type | Reset | Name | Description |
|:------:|:------:|:-------:|:-------|:-------------------------------------------------------------------------------|
| 31:8 | | | | Reserved |
| 7:0 | rw | 0x0 | EN | 0: filter match wil not generate wakeupe; 1: filter match will generate wakeup |
| Bits | Type | Reset | Name |
|:------:|:------:|:-------:|:--------------------------------------|
| 31:9 | | | Reserved |
| 8 | rw | 0x0 | [TRANS_EN](#adc_wakeup_ctl--trans_en) |
| 7:0 | rw | 0x0 | [MATCH_EN](#adc_wakeup_ctl--match_en) |

### adc_wakeup_ctl . TRANS_EN
Wakeup due to FSM transition from low power sampling
mode to normal sampling mode.

Note that this wakeup source is primarily intended for debug purposes.
If enabled all the time, this can lead to many wakeups due to false
positives that are ruled out automatically by adc_ctrl after
transitioning from LP -> NP.

0: transition match will not generate wakeup;
1: transition match will generate wakeup

### adc_wakeup_ctl . MATCH_EN
Filter wakeup source.

0: filter match will not generate wakeup;
1: filter match will generate wakeup

## filter_status
Adc filter match status

Indicates whether a particular filter has matched on all channels.
- Offset: `0x70`
- Reset default: `0x0`
- Reset mask: `0xff`
- Reset mask: `0x1ff`

### Fields

```wavejson
{"reg": [{"name": "COND", "bits": 8, "attr": ["rw1c"], "rotate": 0}, {"bits": 24}], "config": {"lanes": 1, "fontsize": 10, "vspace": 80}}
{"reg": [{"name": "MATCH", "bits": 8, "attr": ["rw1c"], "rotate": 0}, {"name": "TRANS", "bits": 1, "attr": ["rw1c"], "rotate": -90}, {"bits": 23}], "config": {"lanes": 1, "fontsize": 10, "vspace": 80}}
```

| Bits | Type | Reset | Name | Description |
|:------:|:------:|:-------:|:-------|:-----------------------------------------------------------|
| 31:8 | | | | Reserved |
| 7:0 | rw1c | 0x0 | COND | 0: filter condition is not met; 1: filter condition is met |
| 31:9 | | | | Reserved |
| 8 | rw1c | 0x0 | TRANS | 0: transition did not occur; 1: transition occurred |
| 7:0 | rw1c | 0x0 | MATCH | 0: filter condition is not met; 1: filter condition is met |

## adc_intr_ctl
Interrupt enable controls.
Expand All @@ -345,36 +365,57 @@ which internal sources are actually registered.
This register uses the same bit enumeration as [`ADC_INTR_STATUS`](#adc_intr_status)
- Offset: `0x74`
- Reset default: `0x0`
- Reset mask: `0x1ff`
- Reset mask: `0x3ff`

### Fields

```wavejson
{"reg": [{"name": "EN", "bits": 9, "attr": ["rw"], "rotate": 0}, {"bits": 23}], "config": {"lanes": 1, "fontsize": 10, "vspace": 80}}
{"reg": [{"name": "MATCH_EN", "bits": 8, "attr": ["rw"], "rotate": 0}, {"name": "TRANS_EN", "bits": 1, "attr": ["rw"], "rotate": -90}, {"name": "ONESHOT_EN", "bits": 1, "attr": ["rw"], "rotate": -90}, {"bits": 22}], "config": {"lanes": 1, "fontsize": 10, "vspace": 120}}
```

| Bits | Type | Reset | Name | Description |
|:------:|:------:|:-------:|:-------|:-------------------------------------------------------------------|
| 31:9 | | | | Reserved |
| 8:0 | rw | 0x0 | EN | 0: interrupt source is not enabled; 1: interrupt source is enabled |
| Bits | Type | Reset | Name |
|:------:|:------:|:-------:|:----------------------------------------|
| 31:10 | | | Reserved |
| 9 | rw | 0x0 | [ONESHOT_EN](#adc_intr_ctl--oneshot_en) |
| 8 | rw | 0x0 | [TRANS_EN](#adc_intr_ctl--trans_en) |
| 7:0 | rw | 0x0 | [MATCH_EN](#adc_intr_ctl--match_en) |

### adc_intr_ctl . ONESHOT_EN
Interrupt due to oneshot sampling.

0: interrupt source is not enabled; 1: interrupt source is enabled

### adc_intr_ctl . TRANS_EN
Interrupt due to FSM transition from low power sampling
mode to normal sampling mode. This is mainly intended for debug.

Note that this interrupt is primarily intended for debug purposes.

0: interrupt source is not enabled; 1: interrupt source is enabled

### adc_intr_ctl . MATCH_EN
Filter interrupt source.

0: interrupt source is not enabled; 1: interrupt source is enabled

## adc_intr_status
Debug cable internal status
- Offset: `0x78`
- Reset default: `0x0`
- Reset mask: `0x1ff`
- Reset mask: `0x3ff`

### Fields

```wavejson
{"reg": [{"name": "filter_match", "bits": 8, "attr": ["rw1c"], "rotate": 0}, {"name": "oneshot", "bits": 1, "attr": ["rw1c"], "rotate": -90}, {"bits": 23}], "config": {"lanes": 1, "fontsize": 10, "vspace": 90}}
{"reg": [{"name": "MATCH", "bits": 8, "attr": ["rw1c"], "rotate": 0}, {"name": "TRANS", "bits": 1, "attr": ["rw1c"], "rotate": -90}, {"name": "ONESHOT", "bits": 1, "attr": ["rw1c"], "rotate": -90}, {"bits": 22}], "config": {"lanes": 1, "fontsize": 10, "vspace": 90}}
```

| Bits | Type | Reset | Name | Description |
|:------:|:------:|:-------:|:-------------|:-----------------------------------------------------------|
| 31:9 | | | | Reserved |
| 8 | rw1c | 0x0 | oneshot | 0: oneshot sample is not done ; 1: oneshot sample is done |
| 7:0 | rw1c | 0x0 | filter_match | 0: filter condition is not met; 1: filter condition is met |
| Bits | Type | Reset | Name | Description |
|:------:|:------:|:-------:|:--------|:-----------------------------------------------------------|
| 31:10 | | | | Reserved |
| 9 | rw1c | 0x0 | ONESHOT | 0: oneshot sample is not done ; 1: oneshot sample is done |
| 8 | rw1c | 0x0 | TRANS | 0: transition did not occur; 1: transition occurred |
| 7:0 | rw1c | 0x0 | MATCH | 0: filter condition is not met; 1: filter condition is met |

## adc_fsm_state
State of the internal state machine
Expand Down
5 changes: 3 additions & 2 deletions hw/ip/adc_ctrl/doc/theory_of_operation.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,13 @@ In low power mode:
* Similar to normal operation, the ADC power-up delay is controlled by [`adc_pd_ctl.pwrup_time`](registers.md#adc_pd_ctl).
* Once the ADC is powered up, two samples are taken and compared to the filter thresholds.
* If a configurable number of matches, as determined by [`adc_lp_sample_ctl`](registers.md#adc_lp_sample_ctl), are seen, the ADC controller transitions to normal operation for continuous sampling.
* If a match cannot be confirmed in normal operation mode, the ADC controller switches back to low power mode without firmware intervention.

Although it can be used at any time, the periodic operation mode and use of the slow clock allows the ADC controller to continue to scan when most of the chip is in sleep or power-down modes.
The controller can be configured to issue a wakeup to the rest of the chip.

The controller can be configured to issue a wakeup to the rest of the chip.
If a filter is enabled for wakeup in [`adc_wakeup_ctl`](registers.md#adc_wakeup_ctl) and [`filter_status`](registers.md#filter_status) indicates a match, a wakeup is generated to the system power manager.

For debug purposes, a transition from low power mode to normal power mode can also be configured to issue a wakeup to the rest of the chip via [`adc_wakeup_ctl`](registers.md#adc_wakeup_ctl).

## Filters and debounce

Expand Down
4 changes: 2 additions & 2 deletions hw/ip/adc_ctrl/dv/env/adc_ctrl_env_cfg.sv
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@ class adc_ctrl_env_cfg extends cip_base_env_cfg #(
bit lp_mode;

// Interrupt control bits
bit [ADC_CTRL_NUM_FILTERS:0] adc_intr_ctl = 0;
bit [ADC_CTRL_NUM_FILTERS+1:0] adc_intr_ctl = 0;

// Wakeup control bits
bit [ADC_CTRL_NUM_FILTERS-1:0] adc_wakeup_ctl = 0;
bit [ADC_CTRL_NUM_FILTERS:0] adc_wakeup_ctl = 0;

// For longtest, adjust large time value to avoid test timeout
bit fast_mode = 0;
Expand Down
46 changes: 33 additions & 13 deletions hw/ip/adc_ctrl/dv/env/adc_ctrl_scoreboard.sv
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ class adc_ctrl_scoreboard extends cip_base_scoreboard #(
protected bit [ADC_CTRL_NUM_FILTERS - 1 : 0] m_expected_filter_status;
// Debounce detected
protected bit m_debounced;
// Expected adc_intr_status (1 bit per filter + oneshot mode)
protected bit [ADC_CTRL_NUM_FILTERS : 0] m_expected_adc_intr_status;
// 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;
// Write to filter_status
Expand All @@ -54,6 +54,8 @@ class adc_ctrl_scoreboard extends cip_base_scoreboard #(
protected bit m_adc_ctrl_en = 0;
// In low power mode
protected bit m_lp_mode = 0;
// 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;

Expand Down Expand Up @@ -266,8 +268,10 @@ class adc_ctrl_scoreboard extends cip_base_scoreboard #(
"adc_wakeup_ctl": begin
if (addr_phase_write) begin
// Evaluate expected wakeup adc_wakeup_ctl
m_expected_wakeup =
|(m_expected_filter_status & get_field_val(cfg.ral.adc_wakeup_ctl.en, item.a_data));
m_expected_wakeup = (m_lp_to_np_transition &&
get_field_val(cfg.ral.adc_wakeup_ctl.trans_en, item.a_data)) ||
|(m_expected_filter_status &
get_field_val(cfg.ral.adc_wakeup_ctl.match_en, item.a_data));
end
end
"adc_en_ctl": begin
Expand Down Expand Up @@ -311,18 +315,23 @@ class adc_ctrl_scoreboard extends cip_base_scoreboard #(
do_read_check = 1;
if (addr_phase_read) begin
// Latest ADC value
void'(ral.filter_status.predict(
void'(ral.filter_status.match.predict(
.value(m_expected_filter_status), .kind(UVM_PREDICT_READ)
));
void'(ral.filter_status.trans.predict(
.value(m_lp_to_np_transition), .kind(UVM_PREDICT_READ)
));
end
if (addr_phase_write) begin
->m_filter_status_wr_ev;
// Implement W1C
m_expected_filter_status &= (~item.a_data);
{m_lp_to_np_transition, m_expected_filter_status} &= (~item.a_data);
end
// Evaluate expected wakeup for new m_expected_filter_status
m_expected_wakeup = |(m_expected_filter_status &
cfg.ral.adc_wakeup_ctl.get_mirrored_value());
m_expected_wakeup = (m_lp_to_np_transition &&
cfg.ral.adc_wakeup_ctl.trans_en.get_mirrored_value()) ||
|(m_expected_filter_status &
cfg.ral.adc_wakeup_ctl.match_en.get_mirrored_value());
end
"adc_chn0_filter_ctl_0", "adc_chn0_filter_ctl_1", "adc_chn0_filter_ctl_2",
"adc_chn0_filter_ctl_3", "adc_chn0_filter_ctl_4", "adc_chn0_filter_ctl_5",
Expand Down Expand Up @@ -520,17 +529,20 @@ class adc_ctrl_scoreboard extends cip_base_scoreboard #(
end

// Implement One Shot Mode
// One hot interrupt is one bit above the last filter's interrupt
// 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] = cfg.adc_intr_ctl[ADC_CTRL_NUM_FILTERS];
m_expected_intr_state |= cfg.adc_intr_ctl[ADC_CTRL_NUM_FILTERS];
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

// Delayfor edge detection
// Delay for edge detection
m_match_prev = m_match;

// Decode expected wakeup - allow dynamic control
m_expected_wakeup = |(m_expected_filter_status & cfg.ral.adc_wakeup_ctl.get_mirrored_value());
m_expected_wakeup = (m_lp_to_np_transition &&
cfg.ral.adc_wakeup_ctl.trans_en.get_mirrored_value()) ||
|(m_expected_filter_status &
cfg.ral.adc_wakeup_ctl.match_en.get_mirrored_value());
endfunction

// Process normal power debounce
Expand Down Expand Up @@ -604,6 +616,13 @@ class adc_ctrl_scoreboard extends cip_base_scoreboard #(
m_lp_mode = 0;
// Reflect in config object
cfg.lp_mode = 0;
m_lp_to_np_transition = 1;
// 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;
end
end
Expand Down Expand Up @@ -636,6 +655,7 @@ class adc_ctrl_scoreboard extends cip_base_scoreboard #(
m_expected_intr_state = 0;
m_adc_ctrl_en = 0;
m_lp_mode = 0;
m_lp_to_np_transition = 0;
endfunction

// Software reset
Expand Down
4 changes: 2 additions & 2 deletions hw/ip/adc_ctrl/dv/env/seq_lib/adc_ctrl_clock_gating_vseq.sv
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ class adc_ctrl_clock_gating_vseq extends adc_ctrl_filters_polled_vseq;

virtual task configure_adc_ctrl();
adc_ctrl_testmode_e testmode;
bit [ADC_CTRL_NUM_FILTERS:0] adc_intr_ctl;
bit [ADC_CTRL_NUM_FILTERS-1:0] adc_wakeup_ctl;
bit [ADC_CTRL_NUM_FILTERS+1:0] adc_intr_ctl;
bit [ADC_CTRL_NUM_FILTERS:0] adc_wakeup_ctl;

super.configure_adc_ctrl();
// Normal or low power
Expand Down
Loading

0 comments on commit 8ba5e97

Please sign in to comment.