我正在进行VHDL设计并且我已经开始工作了,但是代码非常难看,事实上我似乎正在努力解决语言设计以实现我的目标,这让我觉得有些不对劲。我是VHDL的新手,但是我已经在这个项目的小块工作了将近一个月,所以我有了一般的想法。但是,这部分有点复杂。
我需要一个在信号上升沿(END_ADC)之后产生一个时钟周期长脉冲(LOAD_PULSE)的过程,但是直到从该信号的最新上升沿(END_ADC)经过4个时钟或者第二个信号的下降沿(LVAL)。
为了完成等待期,我建立了一个计时器模块,计算微秒和周期,在这里:
entity uS_generator is
generic(
Frequency : integer := 66 -- Frequency in MHz
);
Port (
CLK : in STD_LOGIC;
RESET : in STD_LOGIC;
T_CNT : out integer range Frequency downto 1 := 1;
uS_CNT : out integer range 65535 downto 0 := 0
);
end uS_generator;
architecture behavior of uS_generator is
signal T_CNT_INT : integer range Frequency downto 1 := 1; -- Counter for 1 uS
signal uS_CNT_INT : integer range 65535 downto 0 := 0;
begin
COUNT: process(CLK, RESET)
begin
if RESET = '1' then
T_CNT_INT <= 1;
uS_CNT_INT <= 0;
elsif rising_edge(CLK) then
if T_CNT_INT = (Frequency - 1) then -- Increment one clock early so last rising edge sees one uS elapsed.
uS_CNT_INT <= uS_CNT_INT + 1;
T_CNT_INT <= T_CNT_INT + 1;
if uS_CNT_INT = 65535 then
uS_CNT_INT <= 0;
end if;
elsif T_CNT_INT = Frequency then
T_CNT_INT <= 1;
else
T_CNT_INT <= T_CNT_INT + 1;
end if;
end if;
end process COUNT;
T_CNT <= T_CNT_INT;
uS_CNT <= uS_CNT_INT;
end behavior;
我用于设计脉冲生成部分的过程如下:
loadPulseProc: process(PIXEL_CLK, END_ADC, RESET)
begin
if RESET = '1' then
PULSE_FLAG <= '0';
LOAD_PULSE <= '0';
elsif rising_edge(END_ADC) then
PULSE_FLAG <= '1';
end if;
if rising_edge(PIXEL_CLK) then
if PULSE_FLAG = '1' and END_ADC = '1' and LVAL <= '0' and ADC_TMR_T >= 4 and LVAL_TMR_T >= 4 then
LOAD_PULSE <= '1', '0' after PIXEL_CLK_T;
PULSE_FLAG <= '0';
end if;
end if;
end process loadPulseProc;
ADCTimerProc: process(END_ADC, RESET)
begin
if RESET = '1' then
ADC_TMR_RST <= '1', '0' after PIXEL_CLK_T/10;
end if;
if rising_edge(END_ADC) then
ADC_TMR_RST <= '1', '0' after PIXEL_CLK_T/10;
end if;
if falling_edge(END_ADC) then
ADC_TMR_RST <= '1', '0' after PIXEL_CLK_T/10;
end if;
end process ADCTimerProc;
LVALTimerProc: process(LVAL, RESET)
begin
if RESET = '1' then
LVAL_TMR_RST <= '1', '0' after PIXEL_CLK_T/10;
end if;
if rising_edge(LVAL) then
LVAL_TMR_RST <= '1', '0' after PIXEL_CLK_T/10;
end if;
if falling_edge(LVAL) then
LVAL_TMR_RST <= '1', '0' after PIXEL_CLK_T/10;
end if;
end process LVALTimerProc;
PIXEL_CLK_T是时钟的周期,为15.152 ns。
这个设计有效,模拟显示它按照我的要求运行,但只有在由于使用了多个rising_edge的falling_edge调用而将其分成真正应该在一起的单独的if语句之后,才能避免错误。据我所知,使用rising_edge和falling_edge似乎只保留给时钟,所以这只是不好的做法?如何避免这种行为,但仍然创建相同的输出?
谢谢!
答案 0 :(得分:8)
是的,rising_edge()/falling_edge()
只应用于时钟信号。虽然它在仿真中工作,但它可能会导致问题和合成中的意外硬件。
综合工具从函数的参数推断出一个时钟,并将这些信号/线放在FPGA的特殊轨道上(假设您的目标是FPGA用于您的设计)。该工具将进一步推断出特殊时钟缓冲器,并在输入时钟引脚不是时钟引脚时发出警告。
引入多个时钟会导致异步设计,并使其易受跨时钟故障的影响。
检测信号的上升沿或下降沿由边沿检测电路完成,如下所示,它将前一个时钟周期中的信号与当前值进行比较。
需要的信号:
signal mySignal_d : std_logic := '0';
signal mySignal_re : std_logic;
需要的逻辑:
mySignal_d <= mySignal when rising_edge(Clock);
mySignal_re <= not mySignal_d and mySignal;
第一行转换为1位D触发器(您也可以使用进程)。当mySignal
从低变为高时,第二行产生一个周期选通信号。我使用*_d
表示原始输入的延迟信号,*_re
表示上升沿。
生成的信号仍然与Clock
同步。