我知道之前曾问过这个问题,但我认为我的问题不同。 我正在尝试为UART接收器编写代码并得到错误827.我对VHDL很新,不知道我做错了什么。有人可以帮我解决一下吗?
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;
use ieee.numeric_std.all;
entity RX_STATE_MACHINE is
port(rxD,DataAck,resetN,Clk_D: in std_logic;
Data: out std_logic_vector(7 downto 0);
DataRdy,ParityErr,StopErr: out std_logic);
end RX_STATE_MACHINE;
architecture Behavioral of RX_STATE_MACHINE is
type stateType is(st1,st2,st3,st4,st5,st6);
signal NS,PS :stateType := st1;
signal cnt : integer range 0 to 15 :=0;
signal sample: integer range 0 to 15;
begin
--Process for memmory system with asynchronic resetN
process(Clk_D,resetN)
begin
if (resetN='0') then
PS <= st1;
elsif rising_edge(Clk_D) then
PS <= NS;
end if;
end process;
--process that generating 16 steps counter
process(Clk_D)
begin
if rising_edge(Clk_D) then
cnt <= (cnt+1) mod(16);
end if;
end process;
process(rxD,cnt,DataAck,resetN,PS)
-- process(rxD,PS)
variable a: integer range 0 to 7;
variable dat: std_logic_vector(7 downto 0);
begin
sample <= (sample+1) mod(16);
case PS is
when st1 =>
if falling_edge(rxD) then
NS <= st2;
else
NS <= st1;--
end if;
when st2 =>
if (rxD='0') then
if (cnt=7) then
NS <= st3;
sample <= 0;
else
NS <= st2;
end if;
else
NS <= st1;
end if;
when st3 =>
if (a<8) then
if (sample=15) then
dat(a):=rxD;
a:=a+1;
end if;
NS <= st3;--
else
a:=0;
NS <= st4;
end if;
-- Data <= (dat(0),dat(1),dat(2),dat(3),dat(4),dat(5),dat(6),dat(7));
when st4 =>
if (sample=15) then
if((dat(0) xor dat(1) xor dat(2) xor dat(3) xor dat(4) xor dat(5) xor dat(6) xor dat(7))=rxD) then
ParityErr <= '0';
else
ParityErr <= '1';
end if;
NS <= st5;
else
NS <= st4;--
end if;
when st5 =>
if (sample=15) then
if(rxD='1') then
StopErr <= '0';
else
StopErr <= '1';
end if;
NS <= st6;
else
NS <= st5;--
end if;
when st6 =>
if rising_edge(DataAck) then
NS <= st1;
else
NS <= st6;--
end if;
end case;
end process;
end Behavioral;
谢谢!
答案 0 :(得分:1)
在可综合代码中,rising_edge只能用于推断寄存器,例如:
process (clk, rst) is
begin
if rst = '1' then
-- reset code
elsif rising_edge(clk) then
-- actual code
end if;
end process;
您正在将一个控制信号(而不是一个时钟)作为参数传递给rising_edge函数,并在进程的case语句中使用rising_edge函数。那不会合成。
要解决此问题:您可以使用一个时钟延迟控制信号,以便您可以写:
if DataAck_d = '0' and DataAck = '1' then
其他提示:
ieee.numeric_std
,这很好。您不需要ieee.std_logic_unsigned
和ieee.std_logic_arith
。sample
,不应包含resetN
。答案 1 :(得分:0)
如果您还没有这样做,我会阅读Xilinx的这篇文章: AR# 14047
您提供的代码属于导致此类错误的方案的第二个示例。
您希望从本文中删除的关键点是:
为了让XST推断同步元素,事件VHDL属性必须出现在最顶层的&#34; IF&#34;你的过程陈述。
rising_edge()
和falling_edge()
功能都使用&#39;事件&#39;传入信号的属性。
如果Clk_D
的固定频率比RxD
或DataAck
的转换速度快(例如MHz与KHz),则在UART总线的情况下可能是真的,那么你可以考虑将这些输入同步到Clk_D
。这将允许您使FSM同步,这(IMO)更容易理解和调试。
我已经创建了一个用于处理UART已恢复数据的同步FSM的示例:
process(clk_D, ResetN)
begin
if (resetN = '1') then
state <= S_IDLE;
elsif (rising_edge(clk_D)) then
rxD_s_d <= rxD_s;
case state is
when S_IDLE =>
cnt <= 0;
bit_cnt <= 0;
-- Wait for start bit.
if (rxD_s = '0' and rxD_s_d = '1') then -- falling edge detect
state <= S_WAIT8;
endif;
when S_WAIT8 =>
-- Wait 8 clock cycles after start bit detect
-- to align count to center of bit.
if (cnt = 8) then
state <= S_WAIT16;
cnt <= 0;
else
cnt <= cnt + 1;
end if;
when S_WAIT16 =>
-- Wait 16 clock cycles to align data to center of
-- next bit.
if (cnt = 16) then
state <= S_CAPTURE;
cnt <= 0;
else
cnt <= cnt + 1;
end if;
when S_CAPTURE =>
-- Shift in Rx data;
data <= data(6 downto 0) & rxD_s;
if (bit_cnt = 7) then
-- All 8 bits captured; we're done.
-- Could do stop bit detection instead of going
-- back to idle.
state <= S_IDLE;
else
bit_cnt <= bit_cnt + 1;
state <= S_WAIT16;
endif;
end case;
end if;
end process;
此示例假定clk_D
的运行速度比UART波特率快16倍。它使用计数器尝试将接收数据线的采样点居中(同步到clk_D
),以避免在亚稳态(过渡边缘)捕获rxD_s
。它也假定没有奇偶校验,可以很容易地添加。
此外,我还没有对此进行模拟,但建议您做一些更好的理解。