Vhdl SPI接口在模拟中工作,但在实际硬件上不工作

Vhdl SPI接口在模拟中工作,但在实际硬件上不工作,vhdl,fpga,xilinx,Vhdl,Fpga,Xilinx,我试图在传输窗口期间在SPI总线上发送多个字节。最初,当输入脉冲较高时,我从闪存ADC采集数据,然后计算其平均值,并在SPI总线上按顺序传输每个平均值。我让SPI vhdl模块工作,当我尝试发送单个字节时,它能够发送数据,但当我尝试发送超过1个字节时,它就不工作了。MOSI线路上有逻辑0,SS线路一直处于高位。这是我尝试发送多个字节的部分 process(SPITrig, Clock, TX_Done, data_count, average2A_s, average2B_s) begin

我试图在传输窗口期间在SPI总线上发送多个字节。最初,当输入脉冲较高时,我从闪存ADC采集数据,然后计算其平均值,并在SPI总线上按顺序传输每个平均值。我让SPI vhdl模块工作,当我尝试发送单个字节时,它能够发送数据,但当我尝试发送超过1个字节时,它就不工作了。MOSI线路上有逻辑0,SS线路一直处于高位。这是我尝试发送多个字节的部分

process(SPITrig, Clock, TX_Done, data_count, average2A_s, average2B_s)
begin
    case data_count is
        when 1 => 
            TX_Data <= average2A_s;
        when 2 => 
            TX_Data <= average2B_s;
        when others => TX_Data <= "0101010101010101";
    end case;
end process;

process(SPIBusy, SPITrig, SPI_Clock_base, data_count, TX_Start) 
begin
     if falling_edge(SPITrig) then
        SPIBusy <= '1';
        TX_Start <= '0';
        data_count <= 0;
        delay_counter <= 0;
     end if;
     if rising_edge(SPI_Clock_base) and SPIBusy = '1' then
        if data_count < 3 then
            if delay_counter = 128 then
                TX_Start <= not TX_Start;
                delay_counter <= 0;
            elsif delay_counter < 128 then
                delay_counter <= delay_counter + 1;
            end if;

         elsif data_count >= 3 then
            TX_Start <= '0';
            delay_counter <= 0;
            SPIBusy <= '0';
        end if;
    end if; 
    if rising_edge(TX_Start) then
        data_count <= data_count + 1;
    end if;
end process;

注:SPI传输序列在平均输出可用时开始,并使用内部信号“SPITRig”触发

查看合成和计时(STA)警告,因为这些警告将指示合成工具是否无法实现与RTL VHDL代码匹配的设计

除非有充分理由使用多个时钟信号,否则上升沿(…)或下降沿(…)的边缘条件只能用于单个公共时钟信号;通常只使用上升沿(…)

在您的设计中,您有三种不同的信号
SPITrig
SPI_Clock_base
TX_Start
,它们的工作原理与时钟类似,这可能会导致时序冲突

例如,在大流程的第一个
if
中,
TX\u Start
data\u count
都在
下降沿(SPITrig)
上更新,在最后一个
if
中,使用
上升沿(TX\u Start)
根据当前
data\u count
值再次更新
数据计数。这在模拟中可能很好,但在硬件中存在信号传播延迟,这取决于路由和其他因素,这些因素可能会对不同的信号产生警惕,因此类似的设计结构可能会在实现中产生问题

如果您的设计有一个完整的静态时序分析(STA)设置,而您在第一次FPGA项目中可能没有这样的设置,那么STA工具将报告时序是否可以满足,并且像上面这样的结构很可能无法满足时序

因此,请重写您的设计以仅使用单个时钟边缘,例如
上升边缘(SPI\u clock\u base)
。为这种设计进行正确的STA定时设置也容易得多,并且过程的灵敏度列表应仅包含时钟和任何异步复位信号(如果使用),如:

process (SPI_Clock_base) is 
begin
  if rising_edge(SPI_Clock_base) then
    ...
  end if;
end process;

最后,初始过程的灵敏度列表应该减少到只包含过程中读取的信号,因为过程只需要对这些信号敏感。如果包含更多的信号,设计不会失败,它会让读者怀疑到底是什么错了;灵敏度列表或代码。

请查看合成和计时(STA)警告,因为这些警告将指示合成工具是否无法实现与RTL VHDL代码匹配的设计

除非有充分理由使用多个时钟信号,否则上升沿(…)
或下降沿(…)的边缘条件只能用于单个公共时钟信号;通常只使用上升沿(…)

在您的设计中,您有三种不同的信号
SPITrig
SPI_Clock_base
TX_Start
,它们的工作原理与时钟类似,这可能会导致时序冲突

例如,在大流程的第一个
if
中,
TX\u Start
data\u count
都在
下降沿(SPITrig)
上更新,在最后一个
if
中,使用
上升沿(TX\u Start)
根据当前
data\u count
值再次更新
数据计数。这在模拟中可能很好,但在硬件中存在信号传播延迟,这取决于路由和其他因素,这些因素可能会对不同的信号产生警惕,因此类似的设计结构可能会在实现中产生问题

如果您的设计有一个完整的静态时序分析(STA)设置,而您在第一次FPGA项目中可能没有这样的设置,那么STA工具将报告时序是否可以满足,并且像上面这样的结构很可能无法满足时序

因此,请重写您的设计以仅使用单个时钟边缘,例如
上升边缘(SPI\u clock\u base)
。为这种设计进行正确的STA定时设置也容易得多,并且过程的灵敏度列表应仅包含时钟和任何异步复位信号(如果使用),如:

process (SPI_Clock_base) is 
begin
  if rising_edge(SPI_Clock_base) then
    ...
  end if;
end process;

最后,初始过程的灵敏度列表应该减少到只包含过程中读取的信号,因为过程只需要对这些信号敏感。如果包含更多的信号,设计不会失败,它会让读者怀疑到底是什么错了;灵敏度列表或代码。

正如Morten Zimer建议的那样,我做了必要的更改,使所有内容与时钟同步。下面是代码,它正在工作。稍后可能会发布示波器的屏幕截图

process(SPITrig, data_count, average2A_s, average2B_s)
        begin
            case data_count is
                when 1 => 
                    TX_Data <= average2A_s;
                when 2 => 
                    TX_Data <= average2B_s;
                when others => TX_Data <= x"0000";
            end case;
        end process;

        SPICycler : process(delay_counter, data_count, SPITrig, SPI_Clock_base, SPIBusy)
        begin
            if rising_edge(SPI_Clock_base) and SPIBusy = '1' then
                if delay_counter < 511 then
                    delay_counter <= delay_counter + 1;
                    TX_Start <= '0';
                else
                    delay_counter <= 0;
                    TX_Start <= '1';
                    data_count <= data_count + 1;
                end if;

            end if;
            if rising_edge(SPI_Clock_base) then
                if SPITrig = '1' then
                    SPIBusy <= '1';
                    data_count <= 0;
                end if;
                if data_count = 3 then
                    SPIBusy <= '0';
                end if;
            end if;
        end process;
过程(SPITrig、数据计数、平均2a、平均2b)
开始
病例数据_计数为
当1=>
TX_数据

TX_Data TX_Data正如Morten Zimer建议的那样,我做了必要的更改,使所有内容与时钟同步。下面是代码,它正在工作。稍后可能会发布示波器的屏幕截图

process(SPITrig, data_count, average2A_s, average2B_s)
        begin
            case data_count is
                when 1 => 
                    TX_Data <= average2A_s;
                when 2 => 
                    TX_Data <= average2B_s;
                when others => TX_Data <= x"0000";
            end case;
        end process;

        SPICycler : process(delay_counter, data_count, SPITrig, SPI_Clock_base, SPIBusy)
        begin
            if rising_edge(SPI_Clock_base) and SPIBusy = '1' then
                if delay_counter < 511 then
                    delay_counter <= delay_counter + 1;
                    TX_Start <= '0';
                else
                    delay_counter <= 0;
                    TX_Start <= '1';
                    data_count <= data_count + 1;
                end if;

            end if;
            if rising_edge(SPI_Clock_base) then
                if SPITrig = '1' then
                    SPIBusy <= '1';
                    data_count <= 0;
                end if;
                if data_count = 3 then
                    SPIBusy <= '0';
                end if;
            end if;
        end process;
过程(SPITrig、数据计数、平均2a、平均2b)
开始
病例数据_计数为
当1=>
TX_数据

谢谢你对我的问题给出了答案。我会做必要的改变然后回到这里。我做了必要的改变