带数组插入的时钟化VHDL过程问题:FIFO仅读取一个数据即退出
问题根源
- 过程仅被调用一次:主进程只在单个时钟沿后执行一次
read_uplink_FIFO,过程运行完毕直接退出,不会持续监听后续时钟沿来读取FIFO。 - 时钟沿逻辑错误:过程内的
if rising_edge(clk)是即时条件判断,不是等待语句——只有调用过程的瞬间恰好是时钟上升沿时,才会执行内部操作,无法等待下一个时钟周期。 - 局部变量生命周期问题:过程内的
rd_cnt是局部变量,每次调用过程都会被重新初始化为0,无法累计读取次数。
解决方案
方案1:用持续运行的进程替代过程(推荐)
测试平台中,独立进程是实现时序循环逻辑的首选,能持续响应时钟沿直到FIFO为空:
-- 把计数变量放在进程外部,保留状态 signal rd_cnt : integer := 0; process(clk) begin if rising_edge(clk) then if fifo_empty_o = '0' then rd_ena_i <= '1'; uplink_fifo_reg(rd_cnt) <= rd_data_o; rd_cnt <= rd_cnt + 1; else rd_ena_i <= '0'; rd_cnt <= 0; -- FIFO空时重置计数 end if; end if; end process; -- 主进程示例:FIFO写入完成后触发读取逻辑 process begin -- 执行FIFO写入操作 -- ... 写入逻辑代码 ... wait until fifo_write_done; -- 假设fifo_write_done是写入完成的标志信号 -- 读取进程已在持续响应时钟,无需额外调用 wait; end process;
方案2:用包含循环等待的过程(仅作演示)
如果一定要用过程,需让过程内部循环等待每个时钟沿,同时将计数变量移到过程外部以保留状态:
-- 定义在过程外部,避免每次调用重置计数 variable rd_cnt : integer := 0; procedure read_uplink_FIFO is begin rd_cnt := 0; -- 每次读取开始前重置计数 loop wait until rising_edge(clk); -- 等待下一个时钟上升沿 exit when fifo_empty_o = '1'; -- FIFO空时退出循环 rd_ena_i <= '1'; uplink_fifo_reg(rd_cnt) <= rd_data_o; rd_cnt := rd_cnt + 1; end loop; rd_ena_i <= '0'; -- 退出后拉低读使能 end procedure; -- 主进程调用示例 process begin -- FIFO写入完成后调用 wait until rising_edge(clk); read_uplink_FIFO; wait; end process;
注意事项
- 测试平台中,进程优先于过程实现时序循环逻辑,过程更适合封装单次复用的组合逻辑,而非持续的时序操作。
- 不要在过程中用
rising_edge做条件判断,应使用wait until rising_edge(clk)等待时钟沿,确保过程能响应每个周期。 - 局部变量仅在过程执行期间有效,若需保留状态,需将变量定义在过程外部(如进程内的信号/变量)。
内容的提问来源于stack exchange,提问作者Sander
相关产品推荐
相关产品推荐

