搜索
bottom↓
回复: 29

求指教,STM32与FPGA使用SPI通信,跨时钟域问题如何解决呢

[复制链接]

出0入0汤圆

发表于 2012-4-10 12:59:23 | 显示全部楼层 |阅读模式
RT

1、STM32作为Master,主频是72MHz,SPI1可以2分频、4分频、8分频、……

2、EP2C5作为Slaver,外部晶振为50MHz

SPI用的是0模式:CPOL=0 CPHA=0 即SCK第一个时钟(上升沿)边沿数据采样,第2个时钟(下降沿)边沿数据被锁存。

一个是36MHz、18MHz、9MHz……
一个是50MHz

时钟如何同步?!用FIFO吗?!

以下的方法经测试貌似不可取

module SPI_slave(clk, SCK, MOSI, MISO, SSEL, LED);

input clk;
input SCK, SSEL, MOSI;
output MISO;

output LED;

// sync SCK to the FPGA clock using a 3-bits shift register
reg [2:0] SCKr;  always @(posedge clk) SCKr <= {SCKr[1:0], SCK};
wire SCK_risingedge = (SCKr[2:1]==2'b01);  // now we can detect SCK rising edges
wire SCK_fallingedge = (SCKr[2:1]==2'b10);  // and falling edges

// same thing for SSEL
reg [2:0] SSELr;  always @(posedge clk) SSELr <= {SSELr[1:0], SSEL};
wire SSEL_active = ~SSELr[1];  // SSEL is active low
wire SSEL_startmessage = (SSELr[2:1]==2'b10);  // message starts at falling edge
wire SSEL_endmessage = (SSELr[2:1]==2'b01);  // message stops at rising edge

// and for MOSI
reg [1:0] MOSIr;  always @(posedge clk) MOSIr <= {MOSIr[0], MOSI};
wire MOSI_data = MOSIr[1];

// we handle SPI in 8-bits format, so we need a 3 bits counter to count the bits as they come in
reg [2:0] bitcnt;

reg byte_received;  // high when a byte has been received
reg [7:0] byte_data_received;

always @(posedge clk)
begin
  if(~SSEL_active)
    bitcnt <= 3'b000;
  else
  if(SCK_risingedge)
  begin
    bitcnt <= bitcnt + 3'b001;

    // implement a shift-left register (since we receive the data MSB first)
    byte_data_received <= {byte_data_received[6:0], MOSI_data};
  end
end

always @(posedge clk) byte_received <= SSEL_active && SCK_risingedge && (bitcnt==3'b111);

// we use the LSB of the data received to control an LED
reg LED;
always @(posedge clk) if(byte_received) LED <= byte_data_received[0];

reg [7:0] byte_data_sent;

reg [7:0] cnt;
always @(posedge clk) if(SSEL_startmessage) cnt<=cnt+8'h1;  // count the messages

always @(posedge clk)
if(SSEL_active)
begin
  if(SSEL_startmessage)
    byte_data_sent <= cnt;  // first byte sent in a message is the message count
  else
  if(SCK_fallingedge)
  begin
    if(bitcnt==3'b000)
      byte_data_sent <= 8'h00;  // after that, we send 0s
    else
      byte_data_sent <= {byte_data_sent[6:0], 1'b0};
  end
end

assign MISO = byte_data_sent[7];  // send MSB first
// we assume that there is only one slave on the SPI bus
// so we don't bother with a tri-state buffer for MISO
// otherwise we would need to tri-state MISO when SSEL is inactive

endmodule



资料来源:http://www.fpga4fun.com/SPI2.html

阿莫论坛20周年了!感谢大家的支持与爱护!!

月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!

出0入442汤圆

发表于 2012-4-10 23:22:39 | 显示全部楼层
SPI协议的模式只和开始状态有关,不管是什么模式,SI总是在SCK上升沿被锁存,SO总是在SCK下降沿输出(JTAG例外)。要注意时序宽松度。该程序跑10M是没问题的,但是跑30M肯定出问题(采样频率应当至少为信号频率的2倍)。注意bitcnt计数器的值:1,2,3,4,5,6,7,0。即本来bitcnt=0时应当输出LSB,结果你输出0了。建议使用两个计数器分别做。

出0入0汤圆

发表于 2012-4-11 00:14:55 | 显示全部楼层
学习一下,最近在做相关的东西。

但是建议是否考虑用DPRAM来经行处理

出0入0汤圆

发表于 2012-4-11 09:12:31 | 显示全部楼层
根本不涉及跨时钟,你用SPI的CLK同步你的FPGA数据.你其他部分随意用你自己FPGA时钟

出0入0汤圆

发表于 2012-4-11 09:45:23 | 显示全部楼层
跟跨时域没关系吧,spi协议由spi的时钟来控制

出0入0汤圆

 楼主| 发表于 2012-4-11 10:10:07 | 显示全部楼层
wye11083 发表于 2012-4-10 23:22
SPI协议的模式只和开始状态有关,不管是什么模式,SI总是在SCK上升沿被锁存,SO总是在SCK下降沿输出(JTAG ...

谢谢,观察入微哦,在数据存取时,我多打了一拍,现在是STM32 --> FPGA数据正确,有时也会出错,STM32 <-- FPGA 收不到数据的。

以下是STM32的代码:SPI是8分频的

#define                SCS_HIGH                GPIO_SetBits(GPIOA, GPIO_Pin_4)
#define                SCS_LOW                GPIO_ResetBits(GPIOA, GPIO_Pin_4)
void SPI1_Configeration(void)
{
        GPIO_InitTypeDef  GPIO_InitStructure;
        SPI_InitTypeDef  SPI_InitStructure;

        RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO|RCC_APB2Periph_GPIOA, ENABLE);

        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;        //NSS(PA.4) 推免输出
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
        GPIO_Init(GPIOA,&GPIO_InitStructure);

        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5|GPIO_Pin_7;        //MOSI(PA.7) SCK(PA.5) 复用推免输出
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
        GPIO_Init(GPIOA,&GPIO_InitStructure);

        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;        //MISO(PA.6) 浮点输入
//        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
        GPIO_Init(GPIOA,&GPIO_InitStructure);

////////////////////////////////////////////////////////////////////////////////////////
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1,ENABLE);                //打开端口复用时钟、SPI1时钟

        SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;         //双线双向全双工
        SPI_InitStructure.SPI_Mode = SPI_Mode_Master;  //主机模式
        SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;  //SPI发送接收8位帧结构
        SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;                 //时钟悬空低
        SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;         //数据捕获于第1个时钟沿
        SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;                  //软件控制NSS型号
        SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8; //比特率8分频
        SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //数据传输从MSB位开始
        SPI_InitStructure.SPI_CRCPolynomial = 7;  //定义了用于CRC值计算的多项式
       
        SPI_Init(SPI1,&SPI_InitStructure);

        SPI_Cmd(SPI1, ENABLE);         //使能SPI1
}

/**********************************************************
函数名称: SPI_SendByte
功    能: SPI1发/收一个字节数据(硬件SPI)
**********************************************************/
unsigned char SPI1_SendByte(unsigned char dt)
{
        SCS_LOW;
       
        //等待SPI1发送完毕
        while((SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_TXE) == RESET));
       
        SPI_I2S_SendData(SPI1,dt);
       
        //等待SPI1接收完毕
        while((SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_RXNE) == RESET));
        SCS_HIGH;
        return SPI_I2S_ReceiveData(SPI1);       
}

FPGA的SPI模块代码: 和上面差不多,由于个人习惯,改了一些名称

//`timescale 1ns/1ps
module SPI_Slave(clk,rst_n,
                                SCK,MOSI,MISO,NSS,INT,
                                Data_Ready,Data_Received
                                );
input clk;                //FPGA clock,50MHz
input rst_n;        //FPGA reset signal,fallingedge is effective
input SCK;                //Master's SPI SCK signal,Idle:0/Risingedge:Sample/Fallingedge:Latched
input MOSI;                //Master Out Slaver In
output MISO;        //Master In Slaver Out
input NSS;                //SPI Chip-select signal
output INT;                //Slaver interrupt signal of requesting to send data to Master

output Data_Ready;        //detect Data_Received ready or not
output[7:0] Data_Received;        //SPI_Bus receive data from the Master
//===============================================================================
//sync SCK to the FPGA clock using a 3-bits shift register
reg[2:0] SCK_r;

always @(posedge clk or negedge rst_n)
        if(!rst_n) SCK_r <= 3'b000;
        else SCK_r <= {SCK_r[1:0],SCK};

wire SCK_risingedge = (SCK_r[2:1]==2'b01);        //Now we can detect SCK rising edges
wire SCK_fallingedge = (SCK_r[2:1]==2'b10);        //and falling edges

//the same thing for NSS
reg[2:0] NSS_r;
always @(posedge clk or negedge rst_n)
        if(!rst_n) NSS_r <= 3'b000;
        else NSS_r <= {NSS_r[1:0],NSS};

wire NSS_Active = ~NSS_r[1];        //NSS is active now
wire NSS_startmessage = (NSS_r[2:1]==2'b10);        //message starts at falling edge
//not be used//wire NSS_endmessage = (NSS_r[2:1]==2'b01);                //message stops at rising edge

//and for MOSI
reg[1:0] MOSI_r;
always @(posedge clk or negedge rst_n)
        if(!rst_n) MOSI_r <= 2'b00;
        else MOSI_r <= {MOSI_r[0],MOSI};

wire MOSI_Data = MOSI_r[1];

//===============================================================================
//we handle SPI in 8-bits format,so we need a 3-bits counter to count the bits as they come in.
reg[2:0] bitcnt;
reg byte_received;        //high while a byte has already been received
reg[7:0] byte_data_received;

always @(posedge clk or negedge rst_n)
        if(!rst_n) begin bitcnt <= 3'b000; byte_data_received <= 7'h00; end
        else if(!NSS_Active) bitcnt <= 3'b000;
        else if(SCK_risingedge) begin
                bitcnt <= bitcnt +1'b1;
                //implement a shift-left register(since we receive the data MSB first)
                byte_data_received <= {byte_data_received[6:0],MOSI_Data};
        end


assign Data_Received = byte_data_received;

always @(posedge clk or negedge rst_n)
        if(!rst_n) byte_received <= 1'b1;
        else
                byte_received <= NSS_Active && SCK_risingedge && (bitcnt==3'b111);
assign Data_Ready = byte_received;
//===============================================================================
//Here we use INT signal for test,we use the LSB of the data received to control an LED
reg INT;
always @(posedge clk) if(Data_Ready) INT <= byte_data_received[0];
// count the messages
reg[7:0] cnt;
always @(posedge clk or negedge rst_n)
        if(!rst_n) cnt <= 8'h00;
        else if(NSS_startmessage) cnt <= cnt + 8'h1;//NSS_Active && SCK_risingedge && (bitcnt==3'b111)

//===============================================================================
reg[7:0] byte_data_send;

always @(posedge clk)
        if(NSS_Active)
        begin
                if(NSS_startmessage) byte_data_send <=cnt; //first byte send in a message is the message count
                else
                        if(SCK_fallingedge)
                        begin
                                if(bitcnt==3'b000) byte_data_send <= 8'h00; //after that,we send 0s
                                else byte_data_send <= {byte_data_send[6:0],1'b0};
                        end
        end
//always @(posedge clk or negedge rst_n)
//        if(!rst_n) byte_data_send <= 8'd123;
//        else if(NSS_Active&&SCK_fallingedge)
//                byte_data_send <= {byte_data_send[6:0],1'b0};
//       
assign MISO = byte_data_send[7];        //send MSB first

endmodule

出0入0汤圆

 楼主| 发表于 2012-4-11 10:12:26 | 显示全部楼层
NJ8888 发表于 2012-4-11 09:12
根本不涉及跨时钟,你用SPI的CLK同步你的FPGA数据.你其他部分随意用你自己FPGA时钟 ...

我也是这么想的 ,但FPGA在SPI数据存取上,由于时钟不同步,会有问题的,我再试试看……

出0入0汤圆

 楼主| 发表于 2012-4-11 10:15:07 | 显示全部楼层
qingyin2009 发表于 2012-4-11 09:45
跟跨时域没关系吧,spi协议由spi的时钟来控制

还不太清楚,自己现在有点糊涂了,网上有人发论文,用的是SAM+FIFO做的

出0入0汤圆

发表于 2012-4-11 11:06:18 | 显示全部楼层
你要有逻辑分析仪或两通道数字示波器,一个看CLK 一个看DO 或DI(看你调试收发哪个)就能发现问题了

出0入442汤圆

发表于 2012-4-11 15:06:53 | 显示全部楼层
这是我的FPGA SPI程序,时序仿真正常,可以跑到130MHz(Spartan-IIE老芯片)。

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date:    13:38:21 04/11/2012
// Design Name:
// Module Name:    SPIGeneralTransceiver
// Project Name:
// Target Devices:
// Tool versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module SPIGeneralTransceiver(
    input int_in_GCLK,
    input int_in_GRST,
       
    input port_in_SPICS,
    input port_in_SPISI,
    input port_in_SPISCK,
    output port_out_SPISO,
       
    output [7:0] int_out_parallel_SPIDO,
    output int_out_SPIDO_parallel_EN,
       
    input [7:0] int_in_parallel_SPIDI,
    input int_in_SPIDI_parallel_EN
    );


        // According to SPI specification, data is latched on rising edge of SCK,
        // and output latch on falling edge of SCK.
       
        // Any time a valid command is received, valid data out is moved to cache.
       
        reg [1:0] r_port_in_SPISCK_delay;
       
        wire w_port_in_SPISCK_Edge = ^r_port_in_SPISCK_delay;
        reg r_port_in_SPICS_delay;
        reg r_port_in_SPISI;
       
        wire w_SPI_Receive_Reset = int_in_GRST & ~r_port_in_SPICS_delay;
       
        always @(posedge int_in_GCLK or negedge int_in_GRST)
                begin
                        if(~int_in_GRST)
                                begin
                                        r_port_in_SPISCK_delay <= 0;
                                end
                        else
                                begin
                                        r_port_in_SPICS_delay <= port_in_SPICS;
                                        r_port_in_SPISCK_delay <= {r_port_in_SPISCK_delay[0],port_in_SPISCK};
                                        r_port_in_SPISI <= port_in_SPISI;
                                end
                end
               
               
               
               
               
        // SPI Receive part.
       
        reg [2:0] rc_SPI_Receive;        // Actually this counter represents SCLK count.
       
       
        reg rs_SPI_Receive;
       
        reg [7:0] r_SPI_Receive_Byte;
        reg r_SPI_Receive_parallel_SPIDO_EN;
       
        assign int_out_parallel_SPIDO = r_SPI_Receive_Byte;
        assign int_out_SPIDO_parallel_EN = r_SPI_Receive_parallel_SPIDO_EN;
       
       
        // Use w_port_in_SPISCK_Edge and r_port_in_SPISCK_delay[0] and r_port_in_SPISI
       
        // SPI Transmit part
       
        reg [7:0] r_int_in_parallel_SPIDI_Cache;
        reg [7:0] r_int_in_parallel_SPIDI;
       
        assign port_out_SPISO = r_int_in_parallel_SPIDI[7];
       
        always @(posedge int_in_GCLK or negedge w_SPI_Receive_Reset)
                begin
                        if(~w_SPI_Receive_Reset)
                                begin
                                        r_int_in_parallel_SPIDI_Cache <= 0;
                                        r_int_in_parallel_SPIDI <= 0;
                                end
                        else
                                begin
                                        if(int_in_SPIDI_parallel_EN)
                                                begin
                                                        r_int_in_parallel_SPIDI_Cache <= int_in_parallel_SPIDI;
                                                end
                                        else
                                                begin
                                                        r_int_in_parallel_SPIDI_Cache <= r_int_in_parallel_SPIDI_Cache;
                                                end
                                        // Validate int_in_SPIDI_parallel_EN and w_port_in_SPISCK_Edge and ~r_port_in_SPISCK_delay[0]
                                        if(rc_SPI_Receive == 0)
                                                begin
                                                        // Load input data
                                                        if(int_in_SPIDI_parallel_EN & ~r_port_in_SPISCK_delay[0])
                                                                begin
                                                                        r_int_in_parallel_SPIDI <= int_in_parallel_SPIDI;
                                                                end
                                                        else
                                                                begin
                                                                        if(w_port_in_SPISCK_Edge & ~r_port_in_SPISCK_delay[0])
                                                                                r_int_in_parallel_SPIDI <= r_int_in_parallel_SPIDI_Cache;
                                                                        else
                                                                                r_int_in_parallel_SPIDI <= r_int_in_parallel_SPIDI;
                                                                end
                                                end
                                        else
                                                begin
                                                        // Shift only on falling edge
                                                        if(w_port_in_SPISCK_Edge & ~r_port_in_SPISCK_delay[0])
                                                                r_int_in_parallel_SPIDI <= {r_int_in_parallel_SPIDI[6:0],1'b0};
                                                        else
                                                                r_int_in_parallel_SPIDI <= r_int_in_parallel_SPIDI;
                                                end
                                end
                end
       
       
       
       
        always @(posedge int_in_GCLK or negedge w_SPI_Receive_Reset)
                begin
                        if(~w_SPI_Receive_Reset)
                                begin
                                        rc_SPI_Receive <= 0;
                                        rs_SPI_Receive <= 0;
                                        r_SPI_Receive_Byte <= 0;
                                        r_SPI_Receive_parallel_SPIDO_EN <= 0;
                                end
                        else
                                begin
                                        case (rs_SPI_Receive)
                                                0:
                                                        begin
                                                                r_SPI_Receive_parallel_SPIDO_EN <= 0;
                                                                // Cache the first rising edge of SCK
                                                                if(w_port_in_SPISCK_Edge & r_port_in_SPISCK_delay[0])
                                                                        begin
                                                                                r_SPI_Receive_Byte <= {r_SPI_Receive_Byte[6:0],r_port_in_SPISI};
                                                                                rc_SPI_Receive <= rc_SPI_Receive + 1;
                                                                                rs_SPI_Receive <= 1;
                                                                        end
                                                                else
                                                                        begin
                                                                                rs_SPI_Receive <= 0;
                                                                        end
                                                        end
                                                1:
                                                        begin
                                                                // Cache the 2-8 rising edge of SCK
                                                                if(w_port_in_SPISCK_Edge & r_port_in_SPISCK_delay[0])
                                                                        begin
                                                                                r_SPI_Receive_Byte <= {r_SPI_Receive_Byte[6:0],r_port_in_SPISI};
                                                                                rc_SPI_Receive <= rc_SPI_Receive + 1;
                                                                                if(rc_SPI_Receive == 7)
                                                                                        begin
                                                                                                // A byte is received
                                                                                                r_SPI_Receive_parallel_SPIDO_EN <= 1;
                                                                                                rs_SPI_Receive <= 0;
                                                                                        end
                                                                                else
                                                                                        begin
                                                                                                // Not ready
                                                                                                rs_SPI_Receive <= 1;
                                                                                        end
                                                                        end
                                                                else
                                                                        begin
                                                                                rs_SPI_Receive <= 1;
                                                                        end
                                                        end
                                        endcase
                                end
                end
               
       

endmodule

输入和输出的EN都是高电平有效,其中int_接口没有延时,直接操作,port_in_有延时,port_out_看设计。
这个是TestBench

`timescale 1ns / 1ps

////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date:   13:59:22 04/11/2012
// Design Name:   SPIGeneralTransceiver
// Module Name:   D:/USBDev/USBDevelop/SPIGeneralTransceiver_tb.v
// Project Name:  USBDevelop
// Target Device:  
// Tool versions:  
// Description:
//
// Verilog Test Fixture created by ISE for module: SPIGeneralTransceiver
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
////////////////////////////////////////////////////////////////////////////////

module SPIGeneralTransceiver_tb;

        // Inputs
        reg int_in_GCLK;
        reg int_in_GRST;
        reg port_in_SPICS;
        reg port_in_SPISI;
        reg port_in_SPISCK;
        reg [7:0] int_in_parallel_SPIDI;
        reg int_in_SPIDI_parallel_EN;

        // Outputs
        wire port_out_SPISO;
        wire [7:0] int_out_parallel_SPIDO;
        wire int_out_SPIDO_parallel_EN;

        // Instantiate the Unit Under Test (UUT)
        SPIGeneralTransceiver uut (
                .int_in_GCLK(int_in_GCLK),
                .int_in_GRST(int_in_GRST),
                .port_in_SPICS(port_in_SPICS),
                .port_in_SPISI(port_in_SPISI),
                .port_in_SPISCK(port_in_SPISCK),
                .port_out_SPISO(port_out_SPISO),
                .int_out_parallel_SPIDO(int_out_parallel_SPIDO),
                .int_out_SPIDO_parallel_EN(int_out_SPIDO_parallel_EN),
                .int_in_parallel_SPIDI(int_out_parallel_SPIDO),
                .int_in_SPIDI_parallel_EN(int_out_SPIDO_parallel_EN)
        );

        initial begin
                // Initialize Inputs
                int_in_GCLK = 0;
                int_in_GRST = 0;
                port_in_SPICS = 1;
                port_in_SPISI = 0;
                port_in_SPISCK = 0;
                int_in_parallel_SPIDI = 0;
                int_in_SPIDI_parallel_EN = 0;

                // Wait 100 ns for global reset to finish
                #100;
        
                // Add stimulus here
                int_in_GRST = 1;
               
                #200;
                port_in_SPICS = 0;
               
                #9000;
                port_in_SPICS = 1;

        end
       
        always begin
                #325;
                forever begin
                        port_in_SPISI = $random;
                        #25;
                        port_in_SPISCK = 1;
                        #50;
                        port_in_SPISCK = 0;
                        #25;
                end
        end
       
       
       
        always #5 int_in_GCLK=~int_in_GCLK;
      
endmodule

习惯于在TestBench中使用串行口自收发,第一,写TestBench方便,第二,有没有错误只要看最后的数据对不对就知道了。

出0入0汤圆

发表于 2012-4-11 15:56:26 | 显示全部楼层
大家讨论的好热烈啊。
我之前也做过SPI Slave(用的是Spartan-3AN),而且是Quad SPI 四根data线的。Host端做处理可以跑到133MHz正确接收数据。

出0入0汤圆

发表于 2012-4-11 16:26:23 | 显示全部楼层
用FPGA 时钟采样SPI CLK的时钟进行处理就可以吧,采样时钟是SPI 时钟的2倍+

出0入0汤圆

发表于 2012-4-11 16:27:01 | 显示全部楼层
一直在用fpga4fun上面的代码 没问题

出0入0汤圆

发表于 2012-4-11 21:29:37 | 显示全部楼层
我也准备在stm32和fpga使用spi进行数据通信,现在做数据的采集硬件电路,关注大家的讨论。把帖子收藏起来。

出0入0汤圆

 楼主| 发表于 2012-4-11 22:08:28 | 显示全部楼层
wye11083 发表于 2012-4-11 15:06
这是我的FPGA SPI程序,时序仿真正常,可以跑到130MHz(Spartan-IIE老芯片)。

`timescale 1ns / 1ps

非常感谢wye11083兄的支持

上面fpga4fun的代码,只有STM32接收FPGA的数据MISO出错,可能是STM32有原因,回头我在测试你的代码看看。

出0入0汤圆

发表于 2012-4-11 22:41:03 | 显示全部楼层
我也准备在stm32和fpga使用spi进行数据通信, mark

出0入442汤圆

发表于 2012-4-11 23:33:10 | 显示全部楼层
本帖最后由 wye11083 于 2012-4-11 23:34 编辑

对了,想到一点,虽然我没用过STM,但我认为你要用STM收SPI数据时,应当先打开SPI接收允许,要不然SPI控制器本身是不知道什么时候该收,什么时候该发,所以就不收了。你看看datasheet,应该能找到对应寄存器的bit。

不好意思,忘了点回复了,请删除。

出0入442汤圆

发表于 2012-4-11 23:33:41 | 显示全部楼层
xzf962 发表于 2012-4-11 22:08
非常感谢wye11083兄的支持

上面fpga4fun的代码,只有STM32接收FPGA的数据MISO出错,可能是STM32有原因, ...


对了,想到一点,虽然我没用过STM,但我认为你要用STM收SPI数据时,应当先打开SPI接收允许,要不然SPI控制器本身是不知道什么时候该收,什么时候该发,所以就不收了。你看看datasheet,应该能找到对应寄存器的bit。

出0入0汤圆

 楼主| 发表于 2012-4-16 18:40:18 | 显示全部楼层
wye11083 发表于 2012-4-11 23:33
对了,想到一点,虽然我没用过STM,但我认为你要用STM收SPI数据时,应当先打开SPI接收允许,要不然SPI控 ...

wye11083兄,经板级验证,你的代码可行。

各位网友,代码使用前,请注意SPI的模式。

注意到一细节:wye11083兄的文档建立时间……再次表示感谢

出0入0汤圆

发表于 2012-4-16 20:34:01 | 显示全部楼层
mark~~~~~~~~~

出60入0汤圆

发表于 2012-5-4 17:12:40 | 显示全部楼层
FPGA收藏

出0入0汤圆

发表于 2012-7-14 13:57:37 | 显示全部楼层
收藏先~~~~~~~~~~~

出0入0汤圆

发表于 2012-9-4 19:27:49 | 显示全部楼层
证实可以用了么??这个涉及到STM和FPGA,理解起来比较吃力啊~

出0入0汤圆

发表于 2012-9-7 09:30:52 | 显示全部楼层
谢谢楼上的分享享!

出0入0汤圆

发表于 2013-2-26 21:08:23 | 显示全部楼层
这帖子太及时了:

为了进行STM32与FPGA之间的通信  我先在STM32与STM32两个板之间通信(主SPI1,从SPI2)  配置时全双工通信   但是数据总是传不正确(有时正确),但是我在一个板子上进行STM32(SPI1与SPI2)通信却可以。   我纠结都将近10天了。。。。   大神们,你们遇见过这问题吗?  有成功的例程吗?  明天我将程序整理一下打上来,
希望大家能帮帮忙!!   看看哪错了

出0入0汤圆

 楼主| 发表于 2013-3-4 15:19:10 | 显示全部楼层
^小K^ 发表于 2013-2-26 21:08
这帖子太及时了:

为了进行STM32与FPGA之间的通信  我先在STM32与STM32两个板之间通信(主SPI1,从SPI2)  ...

上面代码是正确的

出0入0汤圆

发表于 2013-3-4 16:08:58 | 显示全部楼层
看来FPGA嵌入ARM等硬核是未来潮流啊。。。

出0入0汤圆

发表于 2013-3-31 15:26:42 | 显示全部楼层
楼主你好  我最近也在做stm32与fpga的spi通信程序  调试总有问题  麻烦加下qq请教下  371125717 谢谢

出0入0汤圆

发表于 2013-5-15 21:20:54 | 显示全部楼层
MARk,最近用到stm32和Fpga双核心。。。

出0入0汤圆

发表于 2018-4-14 12:32:07 | 显示全部楼层
xzf962 发表于 2012-4-16 18:40
wye11083兄,经板级验证,你的代码可行。

各位网友,代码使用前,请注意SPI的模式。

问题解决了吗?可以参考 下你的源码不?
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-26 08:58

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表