SPI代码详解FPGA-verilog部分(FPGA+STM32)(二)

本文档详细介绍了如何在SPI3模式下,使用STM32作为主机,FPGA作为从机进行通信。代码段展示了在Verilog中设计的SPI模块驱动,该模块根据输入的命令选择Din或Dout端口进行数据传输。在STM32的半双工模式下,数据通过spi_mp模块在FPGA的内部模块间传递。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

声明:本篇文章面向在已对SPI的四种时序有所了解的人

我们采用SPI3模式以及将FPGA作从机,STM32作主机的方式讲解,在STM32控制部分采用的是半双工模式,但其实半双工与全双工区别不大,
稍加修改即可


本片文章是接续上篇文章的,如果未浏览上一篇文章的,可以在此跳转SPI代码详解FPGA-verilog部分(FPGA+STM32)(一)


本部分代码相当于对SPI模块的一个驱动,从SPI模块中进出的数据都要经过spi_mp 这个模块这一层壳

模块工作流程:单片机先拉低cs_cmd,发送的命令dcmd送给sel,sel的值若是0 ~ 7则表明下一次的FPGA发送从输入口Din0 ~ Din7中选择,sel的值若是128 ~ 135则表明下一次的FPGA接收从输出口Dout0 ~ Dout7中选择。|这里的输入输出口是针对SPI模块来说的,因为spi模块接收的数据是要给FPGA其他模块用的,所以SPI模块从单片机中接收的数据送出去就叫做Dout口|


module spi_mp #(
    parameter cmd_width = 8,
	parameter data_width = 32
)
(
    input clk,
    input rstn,
    input spi_scl,
    input spi_sdi,
    input spi_cs_cmd,
    input spi_cs_data,
    input [data_width - 1:0] Din0,
    input [data_width - 1:0] Din1,
    input [data_width - 1:0] Din2,
    input [data_width - 1:0] Din3,
    input [data_width - 1:0] Din4,
    input [data_width - 1:0] Din5,
    input [data_width - 1:0] Din6,
    input [data_width - 1:0] Din7,

    output spi_sdo, 						
    output reg [cmd_width - 1:0] sel,				
    output reg [data_width - 1:0] Dout0,
    output reg [data_width - 1:0] Dout1,
    output reg [data_width - 1:0] Dout2,
    output reg [data_width - 1:0] Dout3,
    output reg [data_width - 1:0] Dout4,
    output reg [data_width - 1:0] Dout5,
    output reg [data_width - 1:0] Dout6,
    output reg [data_width - 1:0] Dout7
);


reg [data_width - 1:0] r_Dout;
reg [data_width - 1:0] r_din;

wire w_cmd_done;
wire w_data_done;
wire [cmd_width - 1:0] w_dcmd;
wire [data_width - 1:0] w_dout;


spi spi_inst(
    .clk(clk),
    .rstn(rstn),
    .spi_scl(spi_scl),
    .spi_sdi(spi_sdi),
    .spi_cs_cmd(spi_cs_cmd),
    .spi_cs_data(spi_cs_data),
    .din(r_Dout),
    .spi_sdo(spi_sdo),
    .cmd_done(w_cmd_done),
    .data_done(w_data_done),
    .dcmd(w_dcmd),
    .dout(w_dout)
    );

    
// 
always @(posedge clk , negedge rstn) begin
    if(!rstn)
        sel <= 0;
    else if(w_cmd_done)
        sel <= w_dcmd;
    else
        sel <= sel;
end

always @(posedge clk , negedge rstn) begin
    if(!rstn)
        r_din <= 0;
    else if(w_data_done)
        if(sel > 127)
            r_din <= w_dout;
        else
            r_din <= r_din;
    else
        r_din <= r_din;
end


// 
always @(posedge clk , negedge rstn) begin
    if(!rstn)
        r_Dout <= 0;
    else
        case (sel)
            0: r_Dout <= Din0;
            1: r_Dout <= Din1;
            2: r_Dout <= Din2;
            3: r_Dout <= Din3;
            4: r_Dout <= Din4;
            5: r_Dout <= Din5;
            6: r_Dout <= Din6;
            7: r_Dout <= Din7;
            default: r_Dout <= r_Dout;
        endcase
end


// 
always @(posedge clk , negedge rstn) begin
    if(!rstn) begin
        Dout0 <= 0;
        Dout1 <= 0;
        Dout2 <= 0;
        Dout3 <= 0;
        Dout4 <= 0;
        Dout5 <= 0;
        Dout6 <= 0;
        Dout7 <= 0;
    end
    else
        case (sel)
            128: Dout0 <= r_din;
            129: Dout1 <= r_din;
            130: Dout2 <= r_din;
            131: Dout3 <= r_din;
            132: Dout4 <= r_din;
            133: Dout5 <= r_din;
            134: Dout6 <= r_din;
            135: Dout7 <= r_din;
            default: begin
                Dout0 <= Dout0;
                Dout1 <= Dout1;
                Dout2 <= Dout2;
                Dout3 <= Dout3;
                Dout4 <= Dout4;
                Dout5 <= Dout5;
                Dout6 <= Dout6;
                Dout7 <= Dout7;
            end
        endcase
end

endmodule

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值