[ spi_host ] Improvements to command queue usage
- Add a CMDQD register to allow FW to monitor the number of segemnts in the current
command queue.
- Update documentation to accurately describe the recently added command queue
- Remove a reference to the Command/Config CDC
- Properly add CmdDepth as a paramter to spi_host.hjson
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 38320ba..82c42d9 100644
--- a/hw/ip/spi_host/data/spi_host.hjson
+++ b/hw/ip/spi_host/data/spi_host.hjson
@@ -44,6 +44,11 @@
type: "int",
default: "64"
},
+ { name: "CmdDepth",
+ desc: "The size of the Cmd FIFO (one segment descriptor per entry)",
+ type: "int",
+ default: "4"
+ }
],
available_output_list: [
{ name: "sck"
@@ -189,6 +194,12 @@
!!CONTROL.RX_WATERMARK entries (32b each).'''
resval: "0x0"
},
+ { bits: "19:16",
+ name: "CMDQD",
+ desc: '''Command queue depth. Indicates how many unread 32-bit words are
+ currently in the command segment queue.''',
+ resval: "0x0"
+ },
{ bits: "15:8",
name: "RXQD",
desc: '''Receive queue depth. Indicates how many unread 32-bit words are
diff --git a/hw/ip/spi_host/doc/_index.md b/hw/ip/spi_host/doc/_index.md
index a80b870..f723fe7 100644
--- a/hw/ip/spi_host/doc/_index.md
+++ b/hw/ip/spi_host/doc/_index.md
@@ -416,11 +416,10 @@
The command interface can allows for any number of segments in a given command.
-There is no command queue for submitting segments to the SPI_HOST IP.
-However a second segment can be placed into the Config/Command CDC whenever {{< regref "STATUS.READY" >}} is high, even if the previous segment is still running.
-The internal state within the Config/Command CDC provides the option of scheduling a second command segement to execute immediately after completion of the current segment.
+Since most SPI Flash transactions typically consist of 3 or 4 segemnts, there is a small command FIFO for submitting segments to the SPI_HOST IP, so that firmware can issue the entire transaction at one time.
-On the other hand, writing a segment description to {{< regref "COMMAND" >}} when {{< regref "STATUS.READY" >}} is low will trigger an error condition, which must be acknowledged by software.
+Writing a segment description to {{< regref "COMMAND" >}} when {{< regref "STATUS.READY" >}} is low will trigger an error condition, which must be acknowledged by software.
+When submitting multiple segments to the the command queue, firmware can also check the {{< regref "STATUS.CMDQD" >}} register to determine how many unprocessed segements are in the FIFO.
## Data Formatting
diff --git a/hw/ip/spi_host/rtl/spi_host.sv b/hw/ip/spi_host/rtl/spi_host.sv
index 1b8537c..bfd1e5a 100644
--- a/hw/ip/spi_host/rtl/spi_host.sv
+++ b/hw/ip/spi_host/rtl/spi_host.sv
@@ -6,6 +6,8 @@
//
//
+// TODO: Implement CMDQD
+
`include "prim_assert.sv"
module spi_host
@@ -43,9 +45,6 @@
import spi_host_cmd_pkg::*;
- // TODO: Make this an actual parameter
- localparam int CmdDepth = 4;
-
spi_host_reg2hw_t reg2hw;
spi_host_hw2reg_t hw2reg;
@@ -270,6 +269,8 @@
logic sw_rst;
+ logic [3:0] cmd_qd;
+
spi_host_command_queue #(
.CmdDepth(CmdDepth)
) u_cmd_queue (
@@ -282,6 +283,7 @@
.core_command_valid_o (core_command_valid),
.core_command_ready_i (core_command_ready),
.error_busy_o (error_busy),
+ .qd_o (cmd_qd),
.sw_rst_i (sw_rst)
);
@@ -330,6 +332,7 @@
assign hw2reg.status.txqd.d = tx_qd;
assign hw2reg.status.rxqd.d = rx_qd;
+ assign hw2reg.status.cmdqd.d = cmd_qd;
assign hw2reg.status.txwm.d = tx_wm;
assign hw2reg.status.rxwm.d = rx_wm;
assign hw2reg.status.rxempty.d = rx_empty;
@@ -339,6 +342,7 @@
assign hw2reg.status.txqd.de = 1'b1;
assign hw2reg.status.rxqd.de = 1'b1;
+ assign hw2reg.status.cmdqd.de = 1'b1;
assign hw2reg.status.txwm.de = 1'b1;
assign hw2reg.status.rxwm.de = 1'b1;
assign hw2reg.status.rxempty.de = 1'b1;
diff --git a/hw/ip/spi_host/rtl/spi_host_command_queue.sv b/hw/ip/spi_host/rtl/spi_host_command_queue.sv
index 6244c15..b07ea4a 100644
--- a/hw/ip/spi_host/rtl/spi_host_command_queue.sv
+++ b/hw/ip/spi_host/rtl/spi_host_command_queue.sv
@@ -19,16 +19,22 @@
output logic core_command_valid_o,
input core_command_ready_i,
+ output logic [3:0] qd_o,
+
output logic error_busy_o,
input sw_rst_i
);
+ localparam int CmdDepthW = prim_util_pkg::vbits(CmdDepth+1);
+
logic command_ready;
assign command_busy_o = ~command_ready;
assign error_busy_o = command_valid_i & command_busy_o;
+ logic [CmdDepthW-1:0] cmd_depth;
+
prim_fifo_sync #(
.Width(spi_host_cmd_pkg::CmdSize),
.Pass(1),
@@ -44,7 +50,9 @@
.rready_i (core_command_ready_i),
.rdata_o (core_command_o),
.full_o (),
- .depth_o ()
+ .depth_o (cmd_depth)
);
+ assign qd_o = 4'(cmd_depth);
+
endmodule : spi_host_command_queue