我试图在发送窗口期间在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截图。
tx = TX Done pin
trig = TX Start ping
c1 = data count
注意:SPI传输序列在平均输出可用时启动,并使用内部信号“SPITRig”触发。
答案 0 :(得分:3)
查看综合和定时(STA)警告,因为这些警告表明综合工具是否无法实现与RTL VHDL代码匹配的设计。
rising_edge(...)
或falling_edge(...)
的边沿条件只能用于单个公共时钟信号,除非有充分的理由使用多个时钟信号;通常只使用rising_edge(...)
。
在您的设计中,您有三个不同的信号SPITrig
,SPI_Clock_base
和TX_Start
,它们像时钟一样工作,这可能会导致时间违规。
例如,在大型流程的第一个if
中,TX_Start
和data_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;