這是SPI橋的叉骨,將叉骨交易從主機轉換為SPI-MEMORY交易。它可用於將SPI閃光燈,EEPROM或RAM映射到處理器的地址空間中。橋樑透明地運行,因此它的行為就像是內存映射的讀/寫內存,因為它隱藏了SPI協議 - 以額外的延遲為代價。因此,橋樑支持實地執行(XIP),允許處理器直接訪問(並執行)指令和位於SPI內存中的數據。
這是NEORV32 RISC-V處理器的另一個“分拆”項目。有一天,可以將橋作為XIP模塊添加到處理器中。
關鍵功能
戒酒 /想法 /幫助
該橋基於單個VHDL文件rtl/wb_spi_bridge.vhd 。頂級實體是wb_spi_bridge ,可以直接對其進行實例化,而無需任何特殊庫。
entity wb_spi_bridge is
generic (
SPI_CLK_DIV : positive ; -- clock divider: f(spi_clk_o) = f(clk_i) / 2*SPI_CLK_DIV, min 2
SPI_ABYTES : positive ; -- number of address bytes in SPI protocol, 1..4
SPI_CPHA : std_ulogic ; -- clock phase
SPI_CPOL : std_ulogic ; -- idle polarity
WB_ADDR_BASE : std_ulogic_vector ( 31 downto 0 ); -- module base address, size-aligned
WB_ADDR_SIZE : positive -- module address space in bytes
);
port (
-- wishbone host interface --
wb_clk_i : in std_ulogic ; -- clock
wb_rstn_i : in std_ulogic ; -- reset, async, low-active
wb_srstn_i : in std_ulogic ; -- reset, SYNC, low-active
wb_adr_i : in std_ulogic_vector ( 31 downto 0 ); -- address
wb_dat_i : in std_ulogic_vector ( 31 downto 0 ); -- read data
wb_dat_o : out std_ulogic_vector ( 31 downto 0 ); -- write data
wb_we_i : in std_ulogic ; -- read/write
wb_sel_i : in std_ulogic_vector ( 03 downto 0 ); -- byte enable
wb_stb_i : in std_ulogic ; -- strobe
wb_cyc_i : in std_ulogic ; -- valid cycle
wb_ack_o : out std_ulogic ; -- transfer acknowledge
wb_err_o : out std_ulogic ; -- transfer error
-- SPI device interface --
spi_csn_o : out std_ulogic ; -- chip-select, low-active
spi_clk_o : out std_ulogic ; -- serial clock
spi_data_i : in std_ulogic ; -- device data output
spi_data_o : out std_ulogic -- controller data output
);
end wb_spi_bridge ;頂級實體實例化了兩個內文件實體:
wb_spi_bridge_link處理SPI內存協議(讀,寫,寫啟用)wb_spi_bridge_phy處理實際的串行外圍接口協議wb_rstn_i )和一個同步一個( wb_srstn_i ),它們都是低活動的。需要異步復位將橋樑帶入定義的狀態。同步重置是可選的,可用於從應用程序邏輯重置橋樑。如果不使用該重置,將此重置綁在1中。
Wishbone-to-Spi橋的應用特定配置是使用頂部實體的通用物進行的。
SPI時鐘頻率是使用SPI_CLK_DIV通用的配置。它定義了一個適用於時鐘輸入clk_i縮放器以獲得實際的SPI時鐘。 SPI時鐘由f_spi = f_main / (2 * SPI_CLK_DIV)定義。時鐘縮放器的最小值為2,導致輸入時鐘速度的最大SPI時鐘速度為1/4。
實際時鐘模式是通過SPI_CPHA和SPI_CPOL配置的。這兩個通用物的組合允許配置四種標準SPI時鐘模式中的任何一個。有關時鐘模式的更多信息,請參見Spi Wikipedia文章。
SPI_ABYTES GENERIC配置了SPI內存的地址大小,該大小由其容量定義。允許的值是1、2、3和4。大多數SPI EEPROM使用的地址大小為16位,導致SPI_ABYTES = 2 。許多標準的SPI閃存存儲器使用24位用於SPI_ABYTES = 3的地址。
橋僅使用三個標準內存命令。如果特定SPI內存的命令不同,則可以在VHDL源文件中調整它們:
-- spi memory opcodes -----------------------------------------------------------
constant cmd_write_c : std_ulogic_vector ( 7 downto 0 ) := x"02" ; -- write data
constant cmd_read_c : std_ulogic_vector ( 7 downto 0 ) := x"03" ; -- read data
constant cmd_wren_c : std_ulogic_vector ( 7 downto 0 ) := x"06" ; -- write enable
-- ------------------------------------------------------------------------------橋的32位基礎地址由WB_ADDR_BASE通用定義。定義SPI內存的容量的被佔用地址空間的大小由WB_ADDR_SIZE GENEL配置。地址空間大小必須是兩個功率,基本地址必須自然與此尺寸保持一致。
示例:具有64KB的SPI Flash(64*1024字節):
WB_ADDR_BASE => 0 x"FFFF0000" ,
WB_ADDR_SIZE => 64 * 1024在這種情況下, 0xFFFF8000的基礎地址將是無效的,因為它與64kb邊界無天然。
主機接口基於Wishbone B4規範。它支持經典和管道的單一訪問轉移。爆發轉移尚未支持。
| 經典模式閱讀訪問示例 | 管道模式寫入訪問示例 |
|---|---|
stb和cyc都保持主張,直到轉移完成為止。cyc保持主張,直到傳輸完成為止。在轉移開始時,僅在一個週期中主張stb 。 |設置確認信號ack (一個週期為活動)時,將完成轉移。這表明成功終止。設置了誤差信號err (一個週期為活動)時,也可以完成轉移。僅當設置了不支持的字節啟用掩碼時,橋樑才會引起誤差信號(見下文)。
橋支撐32位,16位和8位寫入訪問。讀取訪問始終返回完整的32位單詞。請注意,橋樑可訪問小型字節訂單中的內存數據。 sel字節蒙版信號定義了根據訪問的數據數量。支持以下字節蒙版:
sel | r/w | 數據數量 |
|---|---|---|
1111 | 讀 | 完整的32位單詞 |
1111 | 寫 | 完整的32位單詞 |
1100 | 寫 | 高16位半詞 |
0011 | 寫 | 較低的16位半詞 |
0001 | 寫 | 字節0 |
0010 | 寫 | 字節1 |
0100 | 寫 | 字節2 |
1000 | 寫 | 字節3 |
所有剩餘的字節蒙版組合都會引起傳輸誤差( err一個週期設置為一個週期而不是ack )。
橋總是將完整的命令序列發送到SPI內存的任何類型的叉骨轉移(尚未支持爆發)。這意味著內存操作碼,地址位和實際數據都是為每個事務傳輸的。下表顯示了每種類型的交易中通過SPI傳輸的位數。每個位都需要SPI時鐘的一個時鐘。
| r/w | 數據大小 | CMD位 | 地址位 | 數據位 | 總數 |
|---|---|---|---|---|---|
| 讀 | 單詞(32位) | 8 | 8*SPI_ABYTES | 32 | 8 + 8*SPI_ABYTES + 32 |
| 寫 | 單詞(32位) | 8 + 8 | 8*SPI_ABYTES | 32 | 8 + 8 + 8*SPI_ABYTES + 32 |
| 寫 | 半詞(16位) | 8 + 8 | 8*SPI_ABYTES | 16 | 8 + 8 + 8*SPI_ABYTES + 16 |
| 寫 | 字節(8位) | 8 + 8 | 8*SPI_ABYTES | 8 | 8 + 8 + 8*SPI_ABYTES + 8 |
例如,單詞寬的寫入訪問使用24位地址的SPI閃存需要8 + 8 + 8*3 + 32 = 72 SPI時鐘週期。一個SPI時鐘週期等於2 * SPI_CLK_DIV循環clk_i 。
任何類型的寫入訪問都需要設置內存的寫入啟用閂鎖,該閂鎖已發送單個8位命令。
這些項目提供了一個簡單的TestBench sim/wb_spi_bridge_tb.vhd ,可以通過ghdl通過提供腳本來模擬該項目:
wb_spi_bridge/sim$ sh ghdl.sh模擬將使用100MHz時鐘以1ms的速度運行。在此期間,觸發所有支持的(和一個非法的)叉骨訪問。請注意,此測試台旨在用於手動波形檢查 - 這不是自我檢查!波形數據存儲到sim/wb_spi_bridge.vcd ,可以使用gtkwave查看:
wb_spi_bridge/sim$ gtkwave wb_spi_bridge.vcd該橋已被FPGA提供。通過將其直接連接到NEORV32 RISC-V處理器(無wishbone互連)連接到25LC512 SPI EEPROM的NEORV32 RISC-V處理器的叉骨接口端口來測試。
NEORV32軟件示例提供了一個“總線資源管理器”程序,該程序允許通過UART終端執行任意叉骨訪問。該橋可以成功處理所有讀寫操作。此外,NEORV32可以成功地從SPI模塊執行程序。
以下配置的示例映射結果:
SPI_CLK_DIV => 32 ,
SPI_ABYTES => 2 , -- 16-bit addressing
SPI_CPHA => '0' ,
SPI_CPOL => '0' , -- clock mode 0
WB_ADDR_BASE => x"F0000000" ,
WB_ADDR_SIZE => 64 * 1024 EP4CE22F17C6N @100MHz Hierarchy Logic Cells Logic Registers
----------------------------------------------------------------------------
wb_spi_bridge:wb_spi_bridge_inst 233 (115) 174 (88)
wb_spi_bridge_link:wb_spi_bridge_link_inst 118 (16) 86 (8)
wb_spi_bridge_phy:wb_spi_bridge_phy_inst 102 (102) 78 (78)