我有一个令人困惑的问题..作为缓冲过程的一部分,我将一个std_logic_vector分配给另一个,只需执行:
dataRegister <= dataRegisterBuf;
该过程与时钟同步。请参阅此处了解完整流程:
--! This process buffers the data register synced to sclk when state is state_bufferingToSclk and sets registerReady when done
SclkDomainBuffering: process(sclk)
variable step: natural := 0;
begin
if (rising_edge(sclk)) then
if (state = state_bufferingToSclk) then
if (step = 0) then
dataRegister <= dataRegisterBuf;
step := 1;
elsif (step = 1) then
registerReady <= '1';
step := 2;
end if;
else
step := 0;
registerReady <= '0';
end if;
end if;
end process SclkDomainBuffering;
问题是,在Modelsim中模拟这个时,dataRegister不会采用dataRegisterBuf的值,而是每个&#39; 1&#39;在向量中变为&#39; X&#39;。因此,例如,如果dataRegisterBuf是&#34; 00010&#34;,则dataRegister变为&#34; 000X0&#34;。我不能为我的生活找出原因。这是一个模拟显示它发生:http://i.imgur.com/znFgqKl.png
我已经完成了整个代码,但我无法看到任何与众不同的东西。当它发生时,上面代码中的第84行确实执行了,就我所知,这是唯一一个与所讨论的两个寄存器有关的语句。
答案 0 :(得分:1)
这里是根据您的问题和评论创建的Minimal Complete and Verifiable example:
library ieee;
use ieee.std_logic_1164.all;
entity baffling_problem is
end entity;
architecture foo of baffling_problem is
type state_type is (state_bufferingToClk, state_bufferingToSclk);
signal state: state_type; -- defaults to 'LEFT, state_bufferingToClk
signal dataRegisterBuf: std_logic_vector (31 downto 0) :=
(1 | 2 => '1', others => '0');
signal dataRegister: std_logic_vector (31 downto 0) := (others => '0');
signal registerReady: std_logic;
signal sclk: std_logic := '1';
begin
SclkDomainBuffering: process(sclk)
variable step: natural := 0;
begin
if (rising_edge(sclk)) then
if (state = state_bufferingToSclk) then
if (step = 0) then
dataRegister <= dataRegisterBuf;
step := 1;
elsif (step = 1) then
registerReady <= '1';
step := 2;
end if;
else
step := 0;
registerReady <= '0';
end if;
end if;
end process SclkDomainBuffering;
SOMEOTHERPROCESS:
process (state)
begin
if state = state_type'LEFT then -- other than state_bufferingToSclk
dataRegister <= (others => '0');
end if;
end process;
STIMULI:
process
begin
wait for 20 ns;
sclk <= '0';
wait for 5 ns;
sclk <= '1';
wait for 0 ns; -- state transitions in distinct delta cycle
state <= state_bufferingToSclk;
wait for 20 ns;
sclk <= '0';
wait for 5 ns;
sclk <= '1';
wait for 20 ns;
wait;
end process;
end architecture;
这给出了你描述的行为:
参见IEEE Std 1076-2008 14.7.3信号值的传播,14.7.3.1概述:
随着模拟时间的推移,给定驱动器的投影输出波形中的事务(见14.7.2)将依次成为驱动器的值。当驾驶员以这种方式获得新值或者由于为驾驶员安排的力或存款而获得新值时,无论新值是否与先前值不同,该驾驶员在该模拟周期期间被认为是活动的。出于定义驱动程序活动的目的,假定从空事务获取值的驱动程序已获取新值。如果是,则在给定的模拟周期期间,信号被认为是活动的 - 其中一个来源是活跃的 - 其中一个子元素是活跃的 - 信号在端口关联列表中的关联元素的正式部分中命名,并且相应的实际值是活动的 - 信号是已解析信号的子元素,已解析的信号有效 - 为信号安排一个部队,一个存款或一个释放 - 信号是另一个信号的子元素,其中安排了一个部队或一个存款。
因此信号(dataReady(1)和dataReady(2)处于活动状态,其源处于活动状态。
14.7.3.2驱动值中没有包含dataReady的信号是基本信号,参见第3段f)。
为什么你看到dataReady的值为&#34; 00000000000000000000000000000XX0&#34;在14.7.3.3有效值中描述。
VHDL语言描述了如何模拟精心设计的模型以及描述语法和语义。精心设计的模型包括由信号互连的层次结构中描述的过程,而信号的历史不仅仅是价值。信号更新以预计输出波形进行调度(参见10.5信号分配声明)。
许多刚刚开始使用VHDL的用户将他们对其他语言行为的了解应用于VHDL,例如围绕if语句中的条件的多余(但不是禁止)括号。对其他语言的了解并不能解决信号行为(由模拟周期驱动的仿真模型的架构决定。
您要注意的一件事是,进程(11.3)根据显式或隐式等待语句(10.2)暂停和恢复。
所有并发语句都详细说明了进程和/或进程和块语句(11.并发语句)。
子程序调用是表达式(函数,9.3.4)或语句(过程,10.7)。
在计划激活的任何进程(那些投影输出波形与当前模拟时间匹配,14.7.4模型执行,14.7.3.4信号更新)中没有更新信号值。
在多个进程中驱动的信号代表多个硬件集合。问题出现是因为您使用了已解析的数据类型,如果您使用了未解析的数据类型,则会产生精化错误(6.4.2.3信号声明,第8段)。允许已解析的信号具有多个驱动程序。
std_logic元素的解析表可在软件包std_logic_1164的软件包主体中找到(参见脚注15附件A有关访问标准中包含的VHDL软件包源的附带文件的说明)。分辨率表将解析&#39; 0&#39;和一个&#39; 1&#39;到了&#39; X&#39;。
如果这一切听起来很复杂,你可以学习简单的经验法则来预防问题。
在这种情况下,经验法则是始终从单个过程中驱动信号。
答案 1 :(得分:0)
正如评论中的人所说,问题在于另一个进程正在驱动相同的数据寄存器。我不明白,即使其他进程只是在不同的状态下改变了寄存器的值,它仍会在每个其他状态下驱动信号。我通过将与该寄存器相关的所有内容移动到一个进程中来解决问题。