SPI接口在仿真中工作,但在实际硬件上不工作

时间:2015-02-23 11:45:42

标签: vhdl fpga xilinx

我试图在发送窗口期间在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;

它在模拟中运行良好,但硬件上没有输出。找出错误的方法需要你的帮助。 PS:这是我的第一个FPGA项目,所以我的代码可能效率不高。 我还附上了ISIM截图。

http://i.stack.imgur.com/TYDVZ.png 可点击

tx = TX Done pin
trig = TX Start ping
c1 = data count

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

2 个答案:

答案 0 :(得分:3)

查看综合和定时(STA)警告,因为这些警告表明综合工具是否无法实现与RTL VHDL代码匹配的设计。

rising_edge(...)falling_edge(...)的边沿条件只能用于单个公共时钟信号,除非有充分的理由使用多个时钟信号;通常只使用rising_edge(...)

在您的设计中,您有三个不同的信号SPITrigSPI_Clock_baseTX_Start,它们像时钟一样工作,这可能会导致时间违规。

例如,在大型流程的第一个if中,TX_Startdata_count都在falling_edge(SPITrig)和最后if上更新} rising_edge(TX_Start)用于根据当前data_count值再次更新data_count。这可能在仿真中工作正常,但在HW中你有信号传播延迟,这取决于路由和其他可能对不同信号保持警惕的因素,因此像这样的设计结构可能会给实现带来问题。

如果你的设计有一个完整的静态时序分析(STA)设置,你可能第一次参与FPGA项目,那么STA工具将报告时间是否可以见面,像上面这样的结构可能不符合时间安排。

因此,重写您的设计只使用一个时钟边缘,例如rising_edge(SPI_Clock_base)。为这样的设计制作正确的STA时序设置也要容易得多,然后进程的灵敏度列表应该只包含时钟和任何异步复位信号(如果使用的话),如:

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

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

答案 1 :(得分:2)

根据Morten Zilmer的建议,我做了必要的更改,以便与Clock同步一切。以下是代码,它正在运行。可能稍后从示波器发布屏幕截图。

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;