在下面显示的代码中,输出始终为零(商和余数)。即使我把b的值赋给余数,它也给出0。我已经检查了很多次,但我不明白问题是什么。在编译时,它显示了两个警告:
- Initial value of "b" depends on value of signal "divisor".
问题出在哪里?
--除法器
library ieee;
use ieee.numeric_bit.all;
entity unsigned_divider is
port(
-- the two inputs
dividend: in bit_vector(15 downto 0);
divisor : in bit_vector(15 downto 0);
-- the two outputs
quotient : out bit_vector(15 downto 0);
remainder : out bit_vector(15 downto 0)
);
end entity unsigned_divider;
architecture behave of unsigned_divider is
begin
process
variable a : bit_vector(15 downto 0):=dividend;
variable b : bit_vector(15 downto 0):=divisor;
variable p : bit_vector(15 downto 0):= (others => '0');
variable i : integer:=0;
begin
for i in 0 to 15 loop
p(15 downto 1) := p(14 downto 0);
p(0) := a(15);
a(15 downto 1) := a(14 downto 0);
p := bit_vector(unsigned(p) - unsigned(b));
if(p(15) ='1') then
a(0) :='0';
p := bit_vector(unsigned(p) + unsigned(b));
else
a(0) :='1';
end if;
wait for 1 ns;
end loop;
quotient <= a after 1 ns;
remainder <= p after 1 ns;
end process;
end behave;
您应该在流程语句部分中对变量a和b进行显式赋值(作为顺序信号赋值)。声明:
variable a : bit_vector(15 downto 0):=dividend;
variable b : bit_vector(15 downto 0):=divisor;
应为:
variable a : bit_vector(15 downto 0);
variable b : bit_vector(15 downto 0);
在流程声明部分(流程开始后):
a := dividend;
b := divisor;
这些解决了natipar提到的问题,即在初始化期间只将值分配给a和b。
此外,如果您希望有1 ns的延迟,您应该有一个明确的等待语句作为流程语句流程语句部分的最后一个顺序语句:
wait on dividend, divisor;
这些使您的流程语句看起来像这样(添加了缩进):
process
variable a : bit_vector(15 downto 0); -- := dividend;
variable b : bit_vector(15 downto 0); -- := divisor;
variable p : bit_vector(15 downto 0) := (others => '0');
variable i : integer := 0;
begin
a := dividend;
b := divisor;
for i in 0 to 15 loop
p(15 downto 1) := p(14 downto 0);
p(0) := a(15);
a(15 downto 1) := a(14 downto 0);
p := bit_vector(unsigned(p) - unsigned(b));
if p(15) = '1' then
a(0) :='0';
p := bit_vector(unsigned(p) + unsigned(b));
else
a(0) := '1';
end if;
wait for 1 ns;
end loop;
quotient <= a after 1 ns;
remainder <= p after 1 ns;
wait on dividend, divisor;
end process;
(注意数字文字和单位之间的空格,IEEE Std 1076-2008,15.3词汇元素、分隔符和分隔符第4段,最后一句"标识符或抽象文字与相邻标识符或抽象文本之间至少需要一个分隔符",尽管Modelsim没有要求)。
写一个简单的测试台,我们发现你的恢复除法算法中至少有一个错误:
entity unsigned_divider_tb is
end entity;
architecture foo of unsigned_divider_tb is
signal dividend, divisor: bit_vector (15 downto 0) := (others => '0');
signal quotient, remainder: bit_vector (15 downto 0);
function to_string(inp: bit_vector) return string is
variable image_str: string (1 to inp'length);
alias input_str: bit_vector (1 to inp'length) is inp;
begin
for i in input_str'range loop
image_str(i) := character'VALUE(BIT'IMAGE(input_str(i)));
end loop;
return image_str;
end;
begin
DUT:
entity work.unsigned_divider
port map (
dividend,
divisor,
quotient,
remainder
);
MONITOR:
process (quotient, remainder)
begin
report "quotient = " & to_string (quotient) severity NOTE;
report "remainder = " & to_string (remainder) severity NOTE;
end process;
end architecture;
ghdl-一个未签名的除法器.vhdl
ghdl-e unsigned_divider_tb
ghdl-r unsigned_divider_tb
unsigned_divider.vhdl:83:9:@0ms:(报告注释):商=0000000000000000
unsigned_divider.vhdl:84:9:@0ms:(报告注释):余数=0000000000000000
unsigned_divider.vhdl:83:9:@17ns:(报告注释):商=1111111111111111
unsigned_divider.vhdl:84:9:@17ns:(报告注释):余数=0000000000000000
(关于解释,请注意,在0ms时间报告的事务是由于详细说明而执行的默认分配)。
你的算法对0的除法给出了错误的答案。
将刺激过程添加到测试台:
STIMULUS:
process
begin
wait for 20 ns;
dividend <= x"ffff";
divisor <= x"000f";
end process;
表明它也可以得到正确的答案:
unsigned_divider.vhdl:83:9:@37ns:(报告注释):商=0001000100010001
unsigned_divider.vhdl:84:9:@37ns:(报告注释):余数=0000000000000000
通过测试台和在刺激过程中添加的等待语句和任务,你可以进一步探索。
我自己一直都是不恢复除法的粉丝,因为加法或减法需要时钟分频器中的时钟。
变量赋值立即生效;但是,在创建该变量的那一刻,信号没有值,所以你不能期望分配
variable a : bit_vector(15 downto 0):=dividend;
variable b : bit_vector(15 downto 0):=divisor;
以正确工作。不过,我有点惊讶的是,对变量a
的赋值没有任何抱怨。也许这是你的第二次警告。您应该按照自己的方式定义变量,但将赋值留给以后的流程的begin
段。
附言:另外,您可能希望将remainder <= p after 1ns;
更改为remainder <= p after 1 ns;
。