Entity: spi_device
- File: spi_device.sv
Diagram
Description
Copyright lowRISC contributors. Licensed under the Apache License, Version 2.0, see LICENSE for details. SPDX-License-Identifier: Apache-2.0
Serial Peripheral Interface (SPI) Device module.
Generics
Generic name | Type | Value | Description |
---|---|---|---|
NumAlerts | logic [NumAlerts-1:0] | undefined |
Ports
Port name | Direction | Type | Description |
---|---|---|---|
clk_i | input | ||
rst_ni | input | ||
tl_i | input | Register interface | |
tl_o | output | ||
alert_rx_i | input | [NumAlerts-1:0] | Alerts |
alert_tx_o | output | [NumAlerts-1:0] | |
cio_sck_i | input | SPI Interface | |
cio_csb_i | input | ||
cio_sd_o | output | [3:0] | |
cio_sd_en_o | output | [3:0] | |
cio_sd_i | input | [3:0] | |
passthrough_o | output | Passthrough interface | |
passthrough_i | input | ||
intr_rxf_o | output | RX FIFO Full | |
intr_rxlvl_o | output | RX FIFO above level | |
intr_txlvl_o | output | TX FIFO below level | |
intr_rxerr_o | output | RX Frame error | |
intr_rxoverflow_o | output | RX Async FIFO Overflow | |
intr_txunderflow_o | output | TX Async FIFO Underflow | |
ram_cfg_i | input | Memory configuration | |
mbist_en_i | input | DFT related controls | |
scan_clk_i | input | ||
scan_rst_ni | input | ||
scanmode_i | input |
Signals
Name | Type | Description |
---|---|---|
clk_spi_in | logic | clock for latch SDI |
clk_spi_in_muxed | logic | clock for latch SDI |
clk_spi_in_buf | logic | clock for latch SDI |
clk_spi_out | logic | clock for driving SDO |
clk_spi_out_muxed | logic | clock for driving SDO |
clk_spi_out_buf | logic | clock for driving SDO |
reg2hw | spi_device_reg2hw_t | |
hw2reg | spi_device_hw2reg_t | |
tl_sram_h2d | tlul_pkg::tl_h2d_t | |
tl_sram_d2h | tlul_pkg::tl_d2h_t | |
sram_clk | logic | Dual-port SRAM Interface: Refer prim_ram_2p_wrapper.sv |
sram_clk_en | logic | |
sram_clk_ungated | logic | |
sram_clk_muxed | logic | |
sram_rst_n | logic | |
sram_rst_n_noscan | logic | |
mem_a_req | logic | |
mem_a_write | logic | |
mem_a_addr | logic [SramAw-1:0] | |
mem_a_wdata | logic [SramDw-1:0] | |
mem_a_wmask | logic [SramDw-1:0] | |
mem_a_rvalid | logic | |
mem_a_rdata | logic [SramDw-1:0] | |
mem_a_rerror | logic [1:0] | |
mem_b_l2m | sram_l2m_t | |
mem_b_m2l | sram_m2l_t | |
mem_b_req | logic | |
mem_b_write | logic | |
mem_b_addr | logic [SramAw-1:0] | |
mem_b_wdata | logic [SramDw-1:0] | |
mem_b_wmask | logic [SramDw-1:0] | |
mem_b_rvalid | logic | |
mem_b_rdata | logic [SramDw-1:0] | |
mem_b_rerror | logic [1:0] | |
sub_sram_l2m | sram_l2m_t | Submoule SRAM Requests |
sub_sram_m2l | sram_m2l_t | |
internal_sd | logic [3:0] | Host return path mux |
internal_sd_en | logic [3:0] | Host return path mux |
passthrough_sd | logic [3:0] | |
passthrough_sd_en | logic [3:0] | |
sys_sram_l2m | sram_l2m_t | FW, CMDFIFO, ADDRFIFO |
sys_sram_m2l | sram_m2l_t | |
cmdfifo_rvalid | logic | |
cmdfifo_rready | logic | |
cmdfifo_rdata | logic [7:0] | |
cmdfifo_notempty | logic | |
addrfifo_rvalid | logic | |
addrfifo_rready | logic | |
addrfifo_rdata | logic [31:0] | |
addrfifo_notempty | logic | |
cmdfifo_depth | logic [CmdFifoPtrW-1:0] | |
addrfifo_depth | logic [AddrFifoPtrW-1:0] | |
payload_depth | logic [PayloadDepthW-1:0] | |
cpol | logic | Clock polarity |
cpha | logic | Phase : Not complete |
txorder | logic | TX bitstream order: 0(bit 7 to 0), 1(bit 0 to 7) |
rxorder | logic | RX bitstream order: 0(bit 7 to 0), 1(bit 0 to 7) |
abort | logic | Abort current operations (txf only at this time) |
csb_syncd | logic | Think how FW knows abort is done. logic abort_done; // TODO: Not implemented yet |
rst_txfifo_n | logic | |
rst_rxfifo_n | logic | |
rst_txfifo_reg | logic | |
rst_rxfifo_reg | logic | |
spi_mode | spi_mode_e | spi_addr_size_e addr_size; // Not used in fwmode |
cfg_addr_4b_en | logic | spi_byte_t fw_dummy_byte; |
intr_sram_rxf_full | logic | |
intr_fwm_rxerr | logic | |
intr_fwm_rxlvl | logic | |
rxlvl | logic | |
rxlvl_d | logic | |
intr_fwm_txlvl | logic | |
txlvl | logic | |
txlvl_d | logic | |
intr_fwm_rxoverflow | logic | |
intr_fwm_txunderflow | logic | |
rxf_overflow | logic | |
txf_underflow | logic | |
timer_v | logic [7:0] | Wait timer inside rxf control |
sram_rxf_rptr | logic [PtrW-1:0] | |
sram_rxf_wptr | logic [PtrW-1:0] | |
sram_txf_rptr | logic [PtrW-1:0] | |
sram_txf_wptr | logic [PtrW-1:0] | |
sram_rxf_depth | logic [PtrW-1:0] | |
sram_txf_depth | logic [PtrW-1:0] | |
sram_rxf_bindex | logic [SramAw-1:0] | |
sram_txf_bindex | logic [SramAw-1:0] | |
sram_rxf_lindex | logic [SramAw-1:0] | |
sram_txf_lindex | logic [SramAw-1:0] | |
as_txfifo_depth | logic [AsFifoDepthW-1:0] | |
as_rxfifo_depth | logic [AsFifoDepthW-1:0] | |
rxf_empty | logic | |
rxf_full | logic | |
txf_empty | logic | |
txf_full | logic | |
rxf_full_syncd | logic | sync signals |
txf_empty_syncd | logic | sync signals |
io_mode | io_mode_e | |
io_mode_outclk | io_mode_e | |
sub_iomode | io_mode_e | |
s2p_data_valid | logic | |
s2p_data | spi_byte_t | |
s2p_bitcnt | logic [BitCntW-1:0] | |
p2s_valid | logic | |
p2s_data | spi_byte_t | |
p2s_sent | logic | |
sub_p2s_valid | logic | |
sub_p2s_data | spi_byte_t | |
sub_p2s_sent | logic | |
readbuf_addr_sck | logic [31:0] | Read commands related signals |
readbuf_addr_busclk | logic [31:0] | |
cmd_dp_sel | sel_datapath_e | |
cmd_dp_sel_outclk | sel_datapath_e | |
mailbox_assumed | logic | Mailbox in Passthrough needs to take SPI if readcmd hits mailbox address |
passthrough_assumed_by_internal | logic | Mailbox in Passthrough needs to take SPI if readcmd hits mailbox address |
readbuf_threshold | logic [BufferAw:0] | Threshold value of a buffer in bytes |
cmd_filter | logic [255:0] | Passthrouth config signals |
addr_swap_mask | logic [31:0] | |
addr_swap_data | logic [31:0] | |
cmd_info | cmd_info_t [NumCmdInfo-1:0] | Command Info structure |
cmd_info_broadcast | cmd_info_t | Broadcasted cmd_info. cmdparse compares the opcode up to CmdInfoReadCmdEnd and latches the cmd_info and broadcast to submodules |
cmd_info_idx_broadcast | logic [CmdInfoIdxW-1:0] | |
csb_deasserted_busclk | logic | Bus clock pulse event of CSb de-assertion. It is used to latch the SCK domain variables into the bus clock domain. |
status_busy_set | logic | set by HW (upload) |
status_busy_broadcast | logic | from spid_status |
jedec_id | logic [23:0] | Jedec ID |
[SDW+:SramAw] | ||
[SDW+:SramAw] | ||
[SDW+:SramAw] | ||
[SDW+:SramAw] | ||
[PtrW-1:0] | ||
[PtrW-1:0] | ||
rxf_full_q | logic | |
txf_empty_q | logic | |
sram_rxf_full_q | logic | Interrupt Edge |
fwm_rxerr_q | logic | Interrupt Edge |
sram_rxf_full | logic | |
fwm_rxerr | logic | |
[BufferAw:0] | ||
sck_n | logic | //////////////////////////// // Clock & reset control // //////////////////////////// clk_spi cannot use glitch-free clock mux as clock switching in glitch-free requires two clocks to propagate clock selection and enable but SPI clock doesn't exist until it transmits data through SDI |
rst_spi_n | logic | |
scanmode | lc_ctrl_pkg::lc_tx_t [ScanModeUseLast-1:0] | |
csb_sync | logic | CSb deassertion pulse generator |
csb_sync_q | logic | CSb deassertion pulse generator |
csb_sckin_sync_d | logic | CSb pulse |
csb_sckin_sync_q | logic | CSb pulse |
csb_asserted_pulse_sckin | logic | CSb pulse |
readstatus_qe | logic | Begin: Read Status ============================================== |
readstatus_q | logic [23:0] | |
readstatus_d | logic [23:0] | |
unused_busy | logic | Temporary: |
unused_sub_sram_status | logic | Tie unused |
unused_sub_sram_jedec | logic | Tie unused |
unused_cmdfifo_q | logic | |
unused_addrfifo_q | logic | |
sys_sram_l2m_fw_wmask | logic [SramDw-1:0] | ////////////////// Common modules // ////////////////// |
sys_sram_req | logic [SysSramEnd-1:0] | Arbiter among Upload CmdFifo/AddrFifo & FW access |
sys_sram_gnt | logic [SysSramEnd-1:0] | |
sys_sram_addr | logic [SramAw-1:0] | |
sys_sram_write | logic [SysSramEnd-1:0] | |
sys_sram_wdata | logic [SramDw-1:0] | |
sys_sram_wmask | logic [SramDw-1:0] | |
sys_sram_rvalid | logic [SysSramEnd-1:0] | |
sys_sram_rdata | logic [SramDw-1:0] | |
sys_sram_rerror | logic [1:0] | |
unused_sys_sram_gnt | logic | |
alert_test | logic [NumAlerts-1:0] | Register module |
alerts | logic [NumAlerts-1:0] | Register module |
Constants
Name | Type | Value | Description |
---|---|---|---|
FifoWidth | int | $bits(spi_byte_t) | |
FifoDepth | int | 8 | 2 DWords |
SDW | int | $clog2(SramDw/FifoWidth) | |
PtrW | int | SramAw + 1 + SDW | |
AsFifoDepthW | int | $clog2(FifoDepth+1) | |
ReadBufferDepth | int unsigned | spi_device_pkg::SramMsgDepth | |
BufferAw | int unsigned | $clog2(ReadBufferDepth) | |
CmdFifoPtrW | int unsigned | $clog2(SramCmdFifoDepth+1) | |
AddrFifoPtrW | int unsigned | $clog2(SramAddrFifoDepth+1) | |
PayloadByte | int unsigned | SramPayloadDepth | |
PayloadDepthW | int unsigned | $clog2(PayloadByte+1) |
Types
Name | Type | Description |
---|---|---|
sys_sram_e | enum int unsigned { SysSramFw = 0, SysSramCmdFifo = 1, SysSramAddrFifo = 2, SysSramEnd = 3 } |
Upload related interfaces (SRAM, FIFOs) Initially, SysSramEnd was the end of the enum variable. But lint tool raises errors the value being used in the parameter. So changed to localparam |
Processes
- unnamed: ( @(posedge clk_spi_in_buf or negedge rst_ni) )
Type: always_ff
- unnamed: ( @(posedge clk_spi_out_buf or negedge rst_ni) )
Type: always_ff
- unnamed: ( @(posedge clk_i or negedge rst_ni) )
Type: always_ff
- unnamed: ( @(posedge clk_i or negedge rst_ni) )
Type: always_ff
- unnamed: ( )
Type: always_comb
Description
Passthrough config: value shall be stable while SPI transaction is active assign cmd_filter = reg2hw.cmd_filter.q;
- unnamed: ( )
Type: always_comb
Description
Connect command info
- unnamed: ( @(posedge clk_i or negedge rst_ni) )
Type: always_ff
- unnamed: ( @(posedge clk_spi_in_buf or negedge rst_spi_n) )
Type: always_ff
- unnamed: ( @(posedge clk_spi_out_buf or negedge rst_spi_n) )
Type: always_ff
Description
//////////////////////////// SPI_DEVICE mode selector // //////////////////////////// This logic chooses appropriate signals based on input SPI_DEVICE mode. e.g) If FwMode is selected. all data connected to spi_fwmode logic Assume spi_mode does not change dynamically io_mode to spi_s2p io_mode should be affected at the negedge of SPI_CLK based on SPI protocol. the internal io_mode signal is generated by SPI input signals. So, the io_mode should be latched at clk_spi_out to not introduce the timing loop.
example: cmdparse triggers sel_dp at 8th beat of CMD bit. -> readcmd activates, it also changes IoMode if opcode is DualIO or QuadIO commands -> changed io_mode affects spi_s2p module, which again affects cmdparse module.
- unnamed: ( @(posedge clk_spi_out_buf or negedge rst_spi_n) )
Type: always_ff
- unnamed: ( )
Type: always_comb
- unnamed: ( )
Type: always_comb
Instantiations
- u_sync_csb: prim_flop_2sync
- u_sync_rxf: prim_flop_2sync
- u_sync_txe: prim_flop_2sync
- u_scanmode_sync: prim_lc_sync
- u_clk_spi: prim_clock_inv
- u_clk_spi_in_mux: prim_clock_mux2
- u_clk_spi_in_buf: prim_clock_buf
- u_clk_spi_out_mux: prim_clock_mux2
- u_clk_spi_out_buf: prim_clock_buf
- u_csb_rst_scan_mux: prim_clock_mux2
- u_tx_rst_scan_mux: prim_clock_mux2
- u_rx_rst_scan_mux: prim_clock_mux2
- u_sram_clk_sel: prim_clock_mux2
Description
SRAM clock
If FwMode, SRAM clock for B port uses peripheral clock (clk_i)
If FlashMode or PassThrough, SRAM clock for B port uses SPI_CLK
To remove glitch, CG cell is put after clock mux
The enable signal is not synchronized to SRAM_CLK when clock is
switched into SPI_CLK. So, change the clock only when SPI_CLK is
not toggle.
Programming sequence:
Change to SPI_CLK
- Check if SPI line is idle.
- Clear sram_clk_en to 0.
- Change mode to FlashMode or PassThrough
- Set sram_clk_en to 1.
Change to peripheral clk - Check if SPI_CLK is idle
- Clear sram_clk_en to 0.
- Change mode to FwMode
- Set sram_clk_en to 1.
- u_sram_clk_scan: prim_clock_mux2
- u_sram_clk_cg: prim_clock_gating
- u_sram_rst_sel: prim_clock_mux2
- u_sram_rst_scanmux: prim_clock_mux2
- u_s2p: spi_s2p
Description
//////////////////////////
SPI Serial to Parallel //
//////////////////////////
- u_p2s: spi_p2s
- u_fwmode: spi_fwmode
Description
///////////
FW Mode //
///////////
- u_cmdparse: spi_cmdparse
Description
//////////////////
SPI Flash Mode //
//////////////////
- u_spid_status: spid_status
- u_jedec: spid_jedec
Description
End: Read Status ------------------------------------------------
- u_tlul2sram: tlul_adapter_sram
- u_memory_2p: prim_ram_2p_async_adv
- u_reg: spi_device_reg_top