Entity: spi_passthrough

Diagram

int unsigned NumCmdInfo clk_i rst_ni clk_out_i [255:0] cfg_cmd_filter_i [31:0] cfg_addr_mask_i [31:0] cfg_addr_value_i cfg_addr_4b_en_i spi_mode_e spi_mode_i [NumCmdInfo-1:0] cmd_info_i host_sck_i host_csb_i [3:0] host_s_i passthrough_rsp_t passthrough_i mailbox_hit_i [3:0] host_s_o [3:0] host_s_en_o passthrough_req_t passthrough_o event_cmd_filtered_o

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 Passthrough module.

Generics

Generic name Type Value Description
NumCmdInfo int unsigned 16

Ports

Port name Direction Type Description
clk_i input SPI input clk
rst_ni input SPI reset
clk_out_i input SPI output clk
cfg_cmd_filter_i input [255:0] Configurations command filter information is given as 256bit register. It is subject to be changed if command config is stored in DPSRAM. If that is supported, the command config is valid at the 6th command cycle and given only 8 bits.
cfg_addr_mask_i input [31:0] address manipulation
cfg_addr_value_i input [31:0]
cfg_addr_4b_en_i input Address mode
spi_mode_i input spi_mode_e
cmd_info_i input [NumCmdInfo-1:0] Command Info structure
host_sck_i input SPI in Though it would be best if passthrough is able to re-use existing spi_s2p and cmdparse, but passthrough has to implement its own s2p and cmdparse to support the A/B binary scheme.
host_csb_i input
host_s_i input [3:0]
host_s_o output [3:0] clk_out_i domain
host_s_en_o output [3:0] clk_out_i domain
passthrough_o output passthrough_req_t SPI to SPI_HOST and terminal to the downstream device
passthrough_i input passthrough_rsp_t
mailbox_hit_i input Mailbox indicator If a read command falls into the mailbox address and the mailbox feature is enabled, the Read Command process module sends a signal to passthrough to take the control of the SPI line. If this signal asserts during Address phase, passthrough drops CSb to SPI Flash device and waits host's CSb de-assertion.
event_cmd_filtered_o output event cmd_filtered: indicator of the incoming command filtered out

Signals

Name Type Description
st passthrough_st_e
st_d passthrough_st_e
host_s_en_inclk logic [3:0] localparam cmd_type_t CmdInfoNone = '{ addr_en: 1'b 0, addr_swap_en: 1'b 0, addr_4b_affected: 1'b 0, dummy_en: 1'b 0, payload_en: 4'h 0, payload_dir: PayloadIn, addr_size: '0, dummy_size: '0 };
localparam cmd_type_t CmdInfoPayloadIn = '{ addr_en: 1'b 0, addr_swap_en: 1'b 0, addr_4b_affected: 1'b 0, dummy_en: 1'b 0, payload_en: 4'h 1, payload_dir: PayloadIn, addr_size: '0, dummy_size: '0 };
localparam cmd_type_t CmdInfoPayloadOut = '{ addr_en: 1'b 0, addr_swap_en: 1'b 0, addr_4b_affected: 1'b 0, dummy_en: 1'b 0, payload_en: 4'h 2, // S[1] payload_dir: PayloadOut, addr_size: '0, dummy_size: '0 };
localparam cmd_type_t CmdInfoAddrPayloadIn = '{ addr_en: 1'b 1, addr_swap_en: 1'b 0, addr_4b_affected: 1'b 1, dummy_en: 1'b 0, payload_en: 4'h 1, // S[0] only payload_dir: PayloadIn, // Host sends Data addr_size: '0, // Logic decide dummy_size: '0 };
localparam cmd_type_t CmdInfoAddrPayloadInQuad = '{ addr_en: 1'b 1, addr_swap_en: 1'b 0, addr_4b_affected: 1'b 1, dummy_en: 1'b 0, payload_en: 4'h F, // S[3:0] payload_dir: PayloadIn, // Host sends Data addr_size: '0, // Logic decide dummy_size: '0 };
localparam cmd_type_t CmdInfoAddrPayloadOut = '{ addr_en: 1'b 1, addr_swap_en: 1'b 1, addr_4b_affected: 1'b 1, dummy_en: 1'b 0, payload_en: 4'h 2, // S[1] only payload_dir: PayloadOut, // Flash device sends Data addr_size: '0, // Logic decide dummy_size: '0 };
// Address + Dummy + Payload but Address is 3B always localparam cmd_type_t CmdInfoAddr3BDummyPayloadOut = '{ addr_en: 1'b 1, addr_swap_en: 1'b 0, addr_4b_affected: 1'b 0, dummy_en: 1'b 1, payload_en: 4'h 2, // S[1] only payload_dir: PayloadOut, // Flash device sends Data addr_size: '0, // Logic decide dummy_size: 'h 7 };
localparam cmd_type_t CmdInfoAddrDummyPayloadOut = '{ addr_en: 1'b 1, addr_swap_en: 1'b 1, addr_4b_affected: 1'b 1, dummy_en: 1'b 1, payload_en: 4'h 2, // S[1] only payload_dir: PayloadOut, // Flash device sends Data addr_size: '0, // Logic decide dummy_size: 'h 7 };
localparam cmd_type_t CmdInfoAddrDummyPayloadOutDual = '{ addr_en: 1'b 1, addr_swap_en: 1'b 1, addr_4b_affected: 1'b 1, dummy_en: 1'b 1, payload_en: 4'h 3, // S[1:0] only payload_dir: PayloadOut, // Flash device sends Data addr_size: '0, // Logic decide dummy_size: 'h 7 };
localparam cmd_type_t CmdInfoAddrDummyPayloadOutQuad = '{ addr_en: 1'b 1, addr_swap_en: 1'b 1, addr_4b_affected: 1'b 1, dummy_en: 1'b 1, payload_en: 4'h F, // S[3:0] payload_dir: PayloadOut, // Flash device sends Data addr_size: '0, // Logic decide dummy_size: 'h 7 };
localparam cmd_type_t CmdInfoAddr = '{ addr_en: 1'b 1, addr_swap_en: 1'b 0, addr_4b_affected: 1'b 0, // TODO: ?? dummy_en: 1'b 0, payload_en: 4'h 0, payload_dir: PayloadOut, // Flash device sends Data addr_size: '0, // Logic decide dummy_size: 'h 0 }; */ Not synthesizable in DC localparam cmd_type_t PassThroughCmdInfoOld [256] = '{ // 8'h 00 'h 00: CmdInfoNone,
// 8'h 01 Write Status 1 'h 01: CmdInfoPayloadIn, // 8'h 15 Write Statur 2 'h 31: CmdInfoPayloadIn, // 8'h 11 Write Status 3 'h 11: CmdInfoPayloadIn,
// 8'h 02 Page Program 'h 02: CmdInfoAddrPayloadIn, // 8'h 32 Quad Input Page Program : Expect to be filtered 'h 32: CmdInfoAddrPayloadInQuad,
// 8'h 03 Read Data 'h 03: CmdInfoAddrPayloadOut,
// 8'h 04 Write Disable 'h 04: CmdInfoNone,
// 8'h 05 Read Status 1 'h 05: CmdInfoPayloadOut, // 8'h 35 Read Status 2 'h 35: CmdInfoPayloadOut, // 8'h 15 Read Status 3 'h 15: CmdInfoPayloadOut,
// 8'h 06 Write Enable 'h 06: CmdInfoNone,
// 8'h 0B Fast Read 'h 0B: CmdInfoAddrDummyPayloadOut, // 8'h 3B Fast Read Dual Output 'h 3B: CmdInfoAddrDummyPayloadOutDual, // 8'h 6B Fast Read Quad Output 'h 6B: CmdInfoAddrDummyPayloadOutQuad,
// 8'h 20 Sector Erase (4kB) 'h 20: CmdInfoAddr, // 8'h 52 Block Erase (32kB) 'h 52: CmdInfoAddr, // 8'h D8 Block Erase (64kB) 'h D8: CmdInfoAddr,
// 8'h 36 Individual Block Lock 'h 36: CmdInfoAddr, // 8'h 39 Individual Block Unlock 'h 39: CmdInfoAddr, // 8'h 3D Read Block Lock 'h 3D: CmdInfoAddrPayloadOut,
// 8'h 38 Enter QPI : Expect to be filtered 'h 38: CmdInfoNone,
// 8'h 42 Program Security Register // 8'h 44 Erase Security Register // 8'h 48 Read Security Register
// 8'h 4B Read Unique ID
// 8'h 5A Read SFDP 'h 5A: CmdInfoAddr3BDummyPayloadOut,
// 8'h 90 Manufacture/Device ID
// 8'h 9F JEDEC ID 'h 9F: CmdInfoPayloadOut,
default: CmdInfoNone }; */ /////////// Signals // /////////// internal clock
device_s_en_inclk logic [3:0]
is_active logic Indicate Passthrough mode is enabled or not.
opcode logic [7:0]
opcode_d logic [7:0]
unused_opcode_7 logic
filter logic If the filter becomes 1 on the 8th beat, it lowers SCK enable signal to CG cell then, at the 8th posedge of SCK, csb_deassert becomes 1. _ SCK / 7 ___/ 8 ____/ _ filter /XXXXXX/ ___________ __ sck_gate_en __________________ __ csb_deassert ______/
sck_gate_en logic If 1, SCK propagates to the downstream SPI Flash device.
csb_deassert logic CSb to the downstream device control If 1, CSb is de-asserted. This signal is glitch sensitive. This value is changed at SCK posedge. This does not drive CSb output directly. CSb to downstream is OR-ed with this and CSb from host system.
cdb_deassert should be latched at the posedge of SCK. filter signal is computed in between the 7th posedge of SCK and the 8th posedge. As the command bit does not arrive until the 7th negedge of SCK, the filter signal is not valid in the first half of the period. By latching the filter signal at the posedge of the SCK, csb_deassert always shows correct value if the command needs to be filtered or not.
However, the CSb output to the downstream flash device is better to be in the out clock domain. It helps the design constraints to be simpler. So, the csb_deassert is again latched at the outclk (which is the negedge of SCK).
csb_deassert_outclk logic
bitcnt logic [MetaBitCntW-1:0]
addrcnt logic [AddrCntW-1:0] Address or anything host driving after opcode counter
addrcnt_outclk logic [AddrCntW-1:0] Address or anything host driving after opcode counter
dummycnt logic [DummyCntW-1:0] Dummy counter
dummycnt_d logic [DummyCntW-1:0] Dummy counter
mailbox_hit logic Mailbox hit.
cmd_7th logic 7th beat of transaction
cmd_8th logic in 8th beat of transaction
cmd_filter logic [1:0]
cmd_info cmd_info_t
cmd_info_d cmd_info_t
cmd_info_7th cmd_info_t [1:0]
cmd_info_7th_d cmd_info_t [1:0]
addr_size_d logic [AddrCntW-1:0]
cmd_info_latch logic
unused_cmd_info_fields logic Some of the fields of cmd_info are used in the big FSM below. The opcode field and the addr_* fields are ignored because we pick them from cmd_info_d instead (in a different FSM state). We rely on the synthesis tool not to generate the unneeded flops but must explicitly waive lint warnings about unused fields.
addr_set logic Address swap
addr_phase logic
addr_phase_outclk logic
addr_swap logic Based on AddrCnt, the logic swap. TODO: Handle the DualIO, QuadIO cases
dummy_set logic Dummy Counter
dummycnt_zero logic
mbyte_set logic MByte counter
mbytecnt_zero logic
mbyte_cnt logic [1:0]
passthrough_s_en logic [3:0]
StFilter end
StWait end
StDriving end
host_s_en_inclk end
StAddress end
st_d end
endcase end

Constants

Name Type Value Description
MetaMaxBeat int unsigned 8+32+8 Cmd + Addr + Dummy
MetaBitCntW int unsigned $clog2(MetaMaxBeat)

Types

Name Type Description
passthrough_st_e enum logic [2:0] {
StIdle,
StFilter,
StWait,
// // // StDriving,
StHighZ,
// // StAddress,
StMByte }
/////////////// Definitions // /////////////// State

Processes

Type: always_ff

Type: always_ff

Type: always_ff

Description
Command Filter: CSb control

Type: always_ff

Type: always_ff

Description
Bitcnt counter / Bitcnt increases until it hit the max value then wait reset.

Type: always_ff

Type: always_comb

Description
Search opcode @ 7th opcode

Type: always_ff

Type: always_ff

Type: always_comb

Type: always_ff

Type: always_ff

Type: always_ff

Description
Address swap should happen in outclk domain. The state machine operates in inclk domain. The state generates mux selection signal. The signal latched in outclk domain then activates the mux.

Type: always_ff

Type: always_ff

Type: always_ff

Type: always_ff

Type: always_ff

Description

  • END: Passthrough Mux (!important) ------------------------------------ ///////////////// State Machine // /////////////////

Type: always_comb