[ spi_host, rtl/dv/doc ] New "OUTPUT_EN" register
- All SPI_HOST outputs are now disabled by default until the OUTPUT_EN register is set
- Includes a one line change to the SPI_HOST DV environment to activate this
- A description of the new register field has been added to the documentation
Fixes 8920
Signed-off-by: Martin Lueker-Boden <martin.lueker-boden@wdc.com>
diff --git a/hw/ip/spi_host/data/spi_host.hjson b/hw/ip/spi_host/data/spi_host.hjson
index dfb2fa8..5bb9332 100644
--- a/hw/ip/spi_host/data/spi_host.hjson
+++ b/hw/ip/spi_host/data/spi_host.hjson
@@ -108,6 +108,13 @@
the IP from reset.''',
resval: "0x0"
},
+ { bits: "29",
+ name: "OUTPUT_EN",
+ desc: '''Enable the SPI host output buffers for the sck, csb, and sd lines. This allows
+ the SPI_HOST IP to connect to the same bus as other SPI controllers without
+ interference.''',
+ resval: "0x0"
+ },
{ bits: "15:8",
name: "TX_WATERMARK"
desc: '''If !!EVENT_ENABLE.TXWM is set, the IP will send
diff --git a/hw/ip/spi_host/doc/_index.md b/hw/ip/spi_host/doc/_index.md
index b74f81f..f25d983 100644
--- a/hw/ip/spi_host/doc/_index.md
+++ b/hw/ip/spi_host/doc/_index.md
@@ -657,6 +657,11 @@
An unacknowledged error event suspends the core state machine.
+### SPI_HOST Output Enable
+
+In addition to enabling the SPI_HOST FSM, the SPI_HOST outputs must also be enabled for successful operation.
+This can be achieved by also setting the {{< regref "CONTROL.OUTPUT_EN" >}} field when enabling the SPI_HOST FSM.
+
### Component reset
In addition to the global hardware reset, there is a software reset option which completely resets the SPI host.
diff --git a/hw/ip/spi_host/dv/env/seq_lib/spi_host_base_vseq.sv b/hw/ip/spi_host/dv/env/seq_lib/spi_host_base_vseq.sv
index 629379b..ef27f01 100644
--- a/hw/ip/spi_host/dv/env/seq_lib/spi_host_base_vseq.sv
+++ b/hw/ip/spi_host/dv/env/seq_lib/spi_host_base_vseq.sv
@@ -174,6 +174,7 @@
ral.control.rx_watermark.set(spi_host_ctrl_reg.rx_watermark);
// activate spi_host dut
ral.control.spien.set(1'b1);
+ ral.control.output_en.set(1'b1);
csr_update(ral.control);
endtask : program_control_reg
diff --git a/hw/ip/spi_host/dv/env/seq_lib/spi_host_tx_rx_vseq.sv b/hw/ip/spi_host/dv/env/seq_lib/spi_host_tx_rx_vseq.sv
index e006bd0..f969594 100644
--- a/hw/ip/spi_host/dv/env/seq_lib/spi_host_tx_rx_vseq.sv
+++ b/hw/ip/spi_host/dv/env/seq_lib/spi_host_tx_rx_vseq.sv
@@ -55,7 +55,6 @@
endtask
-
// sending tx requests to the agent
virtual task send_trans(spi_transaction_item trans);
spi_segment_item segment = new();
diff --git a/hw/ip/spi_host/dv/env/spi_host_scoreboard.sv b/hw/ip/spi_host/dv/env/spi_host_scoreboard.sv
index f0dcc1d..f08fa56 100644
--- a/hw/ip/spi_host/dv/env/spi_host_scoreboard.sv
+++ b/hw/ip/spi_host/dv/env/spi_host_scoreboard.sv
@@ -35,6 +35,7 @@
spi_host_configopts_t spi_configopts;
// control bits
local bit spien = 1'b0;
+ local bit output_en = 1'b0;
local bit sw_rst = 1'b0;
int in_tx_seg_cnt = 0;
@@ -228,8 +229,9 @@
case (csr_name)
// add individual case item for each csr
"control": begin
- spien = bit'(get_field_val(ral.control.spien, item.a_data));
- sw_rst = bit'(get_field_val(ral.control.sw_rst, item.a_data));
+ spien = bit'(get_field_val(ral.control.spien, item.a_data));
+ output_en = bit'(get_field_val(ral.control.output_en, item.a_data));
+ sw_rst = bit'(get_field_val(ral.control.sw_rst, item.a_data));
if (sw_rst || spien) begin
write_segment_q.delete();
rx_data_q.delete();
diff --git a/hw/ip/spi_host/rtl/spi_host.sv b/hw/ip/spi_host/rtl/spi_host.sv
index 1c41165..0ebf476 100644
--- a/hw/ip/spi_host/rtl/spi_host.sv
+++ b/hw/ip/spi_host/rtl/spi_host.sv
@@ -89,8 +89,13 @@
logic sck;
logic [NumCS-1:0] csb;
logic [3:0] sd_out;
- logic [3:0] sd_en;
+ logic [3:0] sd_en, sd_en_core;
logic [3:0] sd_i;
+ logic output_en;
+
+ assign output_en = reg2hw.control.output_en;
+
+ assign sd_en = output_en ? sd_en_core : 4'h0;
if (NumCS == 1) begin : gen_passthrough_implementation
logic passthrough_en;
@@ -111,9 +116,9 @@
assign pt_sd_en = passthrough_i.s_en;
assign cio_sck_o = passthrough_en ? pt_sck : sck;
- assign cio_sck_en_o = passthrough_en ? pt_sck_en : 1'b1;
+ assign cio_sck_en_o = passthrough_en ? pt_sck_en : output_en;
assign cio_csb_o = passthrough_en ? pt_csb : csb;
- assign cio_csb_en_o = passthrough_en ? pt_csb_en : 1'b1;
+ assign cio_csb_en_o = passthrough_en ? pt_csb_en : output_en;
assign cio_sd_o = passthrough_en ? pt_sd_out : sd_out;
assign cio_sd_en_o = passthrough_en ? pt_sd_en : sd_en;
@@ -123,9 +128,9 @@
`ASSERT(PassthroughNumCSCompat_A, !passthrough_i.passthrough_en, clk_i, rst_ni)
assign cio_sck_o = sck;
- assign cio_sck_en_o = 1'b1;
+ assign cio_sck_en_o = output_en;
assign cio_csb_o = csb;
- assign cio_csb_en_o = {NumCS{1'b1}};
+ assign cio_csb_en_o = {NumCS{output_en}};
assign cio_sd_o = sd_out;
assign cio_sd_en_o = sd_en;
@@ -449,7 +454,7 @@
.sck_o (sck),
.csb_o (csb),
.sd_o (sd_out),
- .sd_en_o (sd_en),
+ .sd_en_o (sd_en_core),
.sd_i,
.rx_stall_o (rx_stall),
.tx_stall_o (tx_stall),
diff --git a/hw/ip/spi_host/rtl/spi_host_reg_pkg.sv b/hw/ip/spi_host/rtl/spi_host_reg_pkg.sv
index 2feb78f..18fd080 100644
--- a/hw/ip/spi_host/rtl/spi_host_reg_pkg.sv
+++ b/hw/ip/spi_host/rtl/spi_host_reg_pkg.sv
@@ -64,6 +64,9 @@
} tx_watermark;
struct packed {
logic q;
+ } output_en;
+ struct packed {
+ logic q;
} sw_rst;
struct packed {
logic q;
@@ -276,11 +279,11 @@
// Register -> HW type
typedef struct packed {
- spi_host_reg2hw_intr_state_reg_t intr_state; // [125:124]
- spi_host_reg2hw_intr_enable_reg_t intr_enable; // [123:122]
- spi_host_reg2hw_intr_test_reg_t intr_test; // [121:118]
- spi_host_reg2hw_alert_test_reg_t alert_test; // [117:116]
- spi_host_reg2hw_control_reg_t control; // [115:98]
+ spi_host_reg2hw_intr_state_reg_t intr_state; // [126:125]
+ spi_host_reg2hw_intr_enable_reg_t intr_enable; // [124:123]
+ spi_host_reg2hw_intr_test_reg_t intr_test; // [122:119]
+ spi_host_reg2hw_alert_test_reg_t alert_test; // [118:117]
+ spi_host_reg2hw_control_reg_t control; // [116:98]
spi_host_reg2hw_configopts_mreg_t [0:0] configopts; // [97:67]
spi_host_reg2hw_csid_reg_t csid; // [66:35]
spi_host_reg2hw_command_reg_t command; // [34:17]
diff --git a/hw/ip/spi_host/rtl/spi_host_reg_top.sv b/hw/ip/spi_host/rtl/spi_host_reg_top.sv
index 36274b0..f577621 100644
--- a/hw/ip/spi_host/rtl/spi_host_reg_top.sv
+++ b/hw/ip/spi_host/rtl/spi_host_reg_top.sv
@@ -187,6 +187,8 @@
logic [7:0] control_rx_watermark_wd;
logic [7:0] control_tx_watermark_qs;
logic [7:0] control_tx_watermark_wd;
+ logic control_output_en_qs;
+ logic control_output_en_wd;
logic control_sw_rst_qs;
logic control_sw_rst_wd;
logic control_spien_qs;
@@ -467,6 +469,31 @@
.qs (control_tx_watermark_qs)
);
+ // F[output_en]: 29:29
+ prim_subreg #(
+ .DW (1),
+ .SwAccess(prim_subreg_pkg::SwAccessRW),
+ .RESVAL (1'h0)
+ ) u_control_output_en (
+ .clk_i (clk_i),
+ .rst_ni (rst_ni),
+
+ // from register interface
+ .we (control_we),
+ .wd (control_output_en_wd),
+
+ // from internal hardware
+ .de (1'b0),
+ .d ('0),
+
+ // to internal hardware
+ .qe (),
+ .q (reg2hw.control.output_en.q),
+
+ // to register interface (read)
+ .qs (control_output_en_qs)
+ );
+
// F[sw_rst]: 30:30
prim_subreg #(
.DW (1),
@@ -1623,6 +1650,8 @@
assign control_tx_watermark_wd = reg_wdata[15:8];
+ assign control_output_en_wd = reg_wdata[29];
+
assign control_sw_rst_wd = reg_wdata[30];
assign control_spien_wd = reg_wdata[31];
@@ -1717,6 +1746,7 @@
addr_hit[4]: begin
reg_rdata_next[7:0] = control_rx_watermark_qs;
reg_rdata_next[15:8] = control_tx_watermark_qs;
+ reg_rdata_next[29] = control_output_en_qs;
reg_rdata_next[30] = control_sw_rst_qs;
reg_rdata_next[31] = control_spien_qs;
end