實現功能:
按字節以spi模式3發送數據,如果要stm32接收,請在cubemx中將對應的spi接口設置為模式3,詳情見代碼開頭注釋
// spi_byte_master.v
// 經過優化的SPI主設備模塊,每次使能發送一個字節。
// 它實現了SPI模式3 (CPOL=1, CPHA=1),即時鐘空閑為高電平,在第二個邊沿(上升沿)采樣數據。module spi_byte_master(input clk, // SPI 工作時鐘 (例如 10MHz)input rst_n, // 異步復位,低有效input ena_mo, // 模塊使能,一個高脈沖觸發一次字節傳輸input [7:0] spi_tdata, // 要發送的8位數據input spi_miso, // SPI MISO 信號output reg spi_mosi, // SPI MOSI 信號output reg spi_sck, // SPI SCK 信號output reg spi_nss, // SPI 片選信號output reg [7:0] spi_rdata, // 接收到的8位數據output tr_done // 一字節傳輸完成信號
);// 狀態機狀態定義localparam S_IDLE = 2'b00; // 等待使能localparam S_TX_L = 2'b01; // SCK 低電平,改變數據localparam S_TX_H = 2'b10; // SCK 高電平,采樣數據localparam S_DONE = 2'b11; // 傳輸完成// 狀態機寄存器reg [1:0] state, next_state;// 位計數器reg [3:0] bit_cnt;// 用于鎖存待發送數據的寄存器reg [7:0] tdata_reg;// FSM - 狀態轉移邏輯 (組合邏輯)always @(*) beginnext_state = state; // 默認保持當前狀態case (state)S_IDLE: beginif (ena_mo)next_state = S_TX_L;endS_TX_L: beginnext_state = S_TX_H;endS_TX_H: begin// 發送完8位后進入完成狀態if (bit_cnt == 4'd7)next_state = S_DONE;elsenext_state = S_TX_L;endS_DONE: begin// 完成后立即返回IDLE,等待下一次觸發next_state = S_IDLE;enddefault: next_state = S_IDLE;endcaseend// FSM - 狀態輸出和數據處理邏輯 (時序邏輯)always @(posedge clk or negedge rst_n) beginif (!rst_n) beginstate <= S_IDLE;bit_cnt <= 4'd0;spi_sck <= 1'b1; // SPI模式3: 空閑時SCK為高spi_mosi <= 1'b0;spi_nss <= 1'b1; // 片選默認無效spi_rdata <= 8'd0;tdata_reg <= 8'd0;end else beginstate <= next_state;// 根據狀態執行操作case (state)S_IDLE: beginspi_nss <= 1'b1; // 在IDLE狀態,取消片選if (ena_mo) beginspi_nss <= 1'b0; // 使能,立即拉低片選,選中從設備bit_cnt <= 4'd0; // 準備發送第一位tdata_reg <= spi_tdata; // 鎖存待發送數據endendS_TX_L: begin// 在SCK下降沿改變數據 (CPHA=1)spi_mosi <= tdata_reg[7 - bit_cnt];spi_sck <= 1'b0;endS_TX_H: beginspi_sck <= 1'b1;// 在SCK上升沿采樣數據 (CPHA=1)spi_rdata[7 - bit_cnt] <= spi_miso;bit_cnt <= bit_cnt + 1;endS_DONE: begin// 傳輸完成,為下一次傳輸做準備bit_cnt <= 4'd0;// nss 信號將會在下一個周期的 IDLE 狀態被拉高endendcaseendend// 完成信號,在S_DONE狀態時拉高一個時鐘周期assign tr_done = (state == S_DONE);endmodule