我有一个简单的设计,我从RS-232端口读取传入的字节,然后解析"它们。
我试图把它分成两个过程:
第一个从串口接收位并尝试构造它们 - 如果成功,它会将结果分配给next_byte
类型unsigned(7 downto 0)
的信号:
-- simplified version
rxbits := serial_rx & rxbits(...);
if (rxbits contain a frame) then:
next_byte <= ....;
rxbits := (others => '1');
end if;
第二个在敏感列表中有next_byte
;它将ascii '0'
/ '1'
转换为位值。我假设在分配next_byte
时会对其进行评估:
-- simplified version
num <= num(...) & ascii_to_bit(next_byte);
当next_byte
发生变化时,似乎过程2的评估次数过多:
'1'
发送到FPGA,num
立即更改为所有'1'
s(我稍后会在七段* 4显示屏上显示它,所以我可以看到)。 '0'
,num
会立即更改所有'0'
。为什么会这样?导致它被评估多次的事件是什么?也许事实上它不是一个简单的&#34;信号(即不是std_logic
)?
顺便说一句,在Xilinx ISE的ISim中运行它并没有按照预期发送'1'
,num
更新后重现这些结果。
另外,如果我删除第二个进程,只需将第一个进程修改为:
-- simplified version
-- next_byte is a variable this time
rxbits := serial_rx & rxbits(...);
if (rxbits contain a frame) then:
next_byte := ....;
num <= num(...) & ascii_to_bit(next_byte);
rxbits := (others => '1');
end if;
一切按预期工作 ...
编辑:我已将代码修改为 sum 接收数字的值(即'1'
将1
添加到num
,'5'
添加5
...)。如果我使用这2个进程运行它,显示(显示num
)只是永远闪烁( - &gt;进程2被称为无限期 ...);如果我使用1个进程运行它,它就可以正常工作。
编辑2:最小,但重现问题:
signal a: unsigned(7 downto 0) := (others => '0');
signal num: unsigned(13 downto 0) := (others => '0');
...
process1: process(clk)
variable counter: unsigned(31 downto 0) := (others => '0');
begin
if rising_edge(clk) then
counter := counter + 1;
if counter(23 downto 0) = 0 then
a <= counter(31 downto 24);
end if;
end if;
end process;
process2: process(a)
begin
num <= num + a;
end process;
num
的显示永远闪烁。
但是在这里:
signal num: unsigned(13 downto 0) := (others => '0');
...
process1: process(clk)
variable counter: unsigned(31 downto 0) := (others => '0');
begin
if rising_edge(clk) then
counter := counter + 1;
if counter(23 downto 0) = 0 then
num <= num + counter(31 downto 24);
end if;
end if;
end process;
它运作正常,num
的显示会随着您的预期而增加。
答案 0 :(得分:1)
您的问题是您希望在合成后观察灵敏度列表。灵敏度列表严格用于模拟。
简化后,模拟器的工作假设是它们只需要在某些输入发生变化时重新评估过程。当指定VHDL时,计算能力来计算哪些信号触发了一个过程中有意义的变化并不容易获得。因此,语言创建者使用模拟工具来告知哪些信号会发生变化,从而手动重新评估过程。
您的问题是您在敏感列表中遗漏了一个信号:pair<CDrug, pair<unsigned,double>> expirednull(pair<CDrug,
pair<unsigned,double>> temp){
if (temp.first.isValid() == false)
temp.second.first = 0;
return temp;
}
string checkForExpiredDrugs() {
stringstream s;
vector<CDealer>::iterator it1;
map<CDrug, pair<unsigned, double>> d;
map<CDrug, pair<unsigned, double>>::iterator it2;
//transform algorithm
for (it1 = this->m_dealers.begin(); it1 != this->m_dealers.end(); it1++) {
s << "Dealer: " << it1->getCompany() << " " << it1->getRepresentative() << " " << it1->getTelephone() << endl;
d = it1->getDrugs();
transform(d.begin(),d.end(),d.begin(),expirednull);
for (it2 = d.begin(); it2 != d.end(); it2++) {
if (it2->first.isValid() == false) {
it2->second.first = 0;
s << "Expired: " << it2->first << endl;
}
}
it1->setDrugs(d);
}
return s.str();
}
num
您希望仅在更改时评估此内容。但是,硬件并没有这样做!在硬件中,这只是一个具有正反馈回路的加法器,因此它将继续一直添加。要在测试平台中查看正确的行为,请将process2: process(a)
begin
num <= num + a;
end process;
添加到敏感度列表中,因为如果仔细观察,您会发现在您的流程中也会读取num
。
num
现在,您将在模拟工具中看到正确的行为,并且可能会收到一条消息,表明您已超过每个步骤的最大评估数。
想一想:
process2: process(a, num)
begin
num <= num + a;
end process;
正如您所观察到的那样,显示屏会永远闪烁,因为num处于一个恒定的递增状态。
正如您也发现的那样,解决方法是让您的加法器同步。添加t = 0: num is 00, a is 00, num + a is also zero
t = 1: a changes to 01 due to your UART receiving '1'
num is 000, a is 01, num + a = 001
num is 001, a is 01, num + a = 002
num is 002, a is 01, num + a = 003
num is 003, a is 01, num + a = 004
num is 004, a is 01, num + a = 005
num is 005, a is 01, num + a = 006
num is 006, a is 01, num + a = 007
num is 007, a is 01, num + a = 008
num is 008, a is 01, num + a = 009
...
num is 255, a is 01, num + a = 000
num is 000, a is 01, num + a = 001
...
t = 2: simulator will never reach this point in time
信号,该信号仅在一个时钟周期内被置位,以指示从UART到达的新字符。 <{1}}被声明后,只能valid
添加a
。
但在更改设计中的任何内容之前,您应该查看综合工具的输出。您的综合工具可能已经指出a)错误的灵敏度列表和b)设计中的组合循环。
您必须学会阅读综合工具的输出,并了解哪些警告只是警告,哪些警告表明您的设计存在致命缺陷。