0

我是 VHDL 的新手,我正在尝试做一个二进制到 BCD 转换器,我在互联网上搜索过,现在我正在尝试自己理解它和 VHDL,这是我的程序:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
use IEEE.NUMERIC_STD.ALL;

-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity Binary_to_BCD is
--generic(n: integer := 2);
    Port ( data     : in unsigned (7 downto 0);
              bcdout : out unsigned (11 downto 0));
end Binary_to_BCD;

architecture Behavioral of Binary_to_BCD is
    -- Inicio el proceso de conversion
    begin
    convert : process (data) is
        variable i : integer := 0;
        variable bin : unsigned (7 downto 0) := data;
        variable bcd : unsigned (11 downto 0) := to_unsigned(0, 12);
        begin
        -- Repito por el numero de bits
        for i in 0 to 7 loop
            bcd := bcd sll 1;       -- Desplazo un lugar a la izquierda el BCD
            bcd(0) := bin(7);       -- Ingreso el nuevo bit al BCD
            bin := bin sll 1;       -- Desplazo el bit que saque antes a la izquierda

            -- Compruebo cada grupo de 4 bits del BCD, si se pasa de 4 le sumo 3
            if(bcd(11 downto 8) > "0101") then
                bcd(11 downto 8) := bcd(11 downto 8) + "0011";
            end if;

            if(bcd(7 downto 4) > "0101") then
                bcd(7 downto 4) := bcd(7 downto 4) + "0011";
            end if;

            if(bcd(3 downto 0) > "0101") then
                bcd(3 downto 0) := bcd(3 downto 0) + "0011";
            end if;

        end loop;
        bcdout := bcd;
    end process convert;
end Behavioral;

我在第 66 行收到此错误bcdout := bcd;

Signal 'bcdout' bcdout is at left hand side of variable assignment statement.

在阅读了网络和书籍之后,我使用unsigned了而不是std_logic_vector因为我需要旋转位和算术运算,但它仍然没有合成。

尝试更改unsignedinteger更改:=<=没有任何效果。这应该是非常愚蠢的事情,但我没有意识到。非常感谢您提前。

4

3 回答 3

2

直接的问题是不正确地使用变量赋值而不是信号的:=信号赋值- 正如错误消息和其他答案所指出的那样。<=bcdout

但是,对于您在 VHDL 过程中所处的位置存在潜在的混淆,这在开始时并不罕见 - 正如有关函数的评论中所揭示的那样。

解决这种混淆的一种常见方法是指出“VHDL 用于硬件设计而不是编程”——虽然在某些方面很有用——可能会导致 VHDL 的人为原始和痛苦的低级使用,这确实阻碍了它。

以“软件方式”编写 VHDL 可以工作 - 并且非常好 - 但是它确实需要更广泛的软件和硬件工程视角,而不是仅仅通过学习 C。

上面的代码可能是可综合的并且可能会工作 - 但它几乎肯定不会像你认为的那样做。然而,一些小的变化是有序的,而不是完全不同的方法。

一些建议可能会有所帮助:

C 函数的 VHDL 等效项是 VHDL 函数。
VHDL 程序的 C 等价物是一个 void 函数。
(是的,C 有程序:它只是将它们称为相反的 void 函数!:-)
VHDL 过程的 C 等价物是......一个过程。换句话说,一个完整的 C 程序,只要它不使用 pthread 或 fork/join。

现在您可以看到,VHDL 是为并行计算而设计的,其方式比任何 C 方言都更加精简——进程只是构建块,信号是进程之间消息传递或共享存储的可靠形式。

所以,在一个进程中,你可以(在一定程度上)用软件术语来思考——但是把一个进程当作一个函数来“调用”是一个巨大的错误。抱歉,如果您以前看过此问答,但它将有助于理解 VHDL 进程的语义,以及进程之间的信号使用。

现在,关于您的代码的具体问题:

1) 它是异步的,即非时钟的。这意味着,保证它如何响应输入上的故障是……困难的……而且知道结果何时有效比你需要的更难。就像在 C 中不受控制地使用全局变量一样 - 不是最佳实践!

因此,转向时钟流程以获得更安全、更可分析的设计。这也是以后提高速度的一步。但是现在,将 VHDL 时钟进程视为事件循环或 C 中的中断处理程序。它在被告知时唤醒,在(有效)零时间执行,并且 sleep()s 直到下一次。

convert : process (clk) is
    variable bin : unsigned (7 downto 0);
    ...
begin
    if rising_edge(clk) then
       bin := data;
       for i in 0 to 7 loop
          ...
       end loop;
    end if;
    bcdout <= bcd;
end process convert;

2) 循环将展开并生成大量硬件。这可能不是问题:它将相当快地交付结果(与等效的软件不同!)有一些方法可以减少硬件使用(状态机)或提高其速度(流水线,上面的链接),但他们现在可以等待。 ..

3)这实际上是您原来的最大问题:您对datato的分配bin实际上是一个过程变量初始化而不是一个分配!它仅在 t=0 时执行一次……这是您所见过的任何误操作的最可能原因。

data上面修改后的时钟示例在每次唤醒进程时分配最新值:即每个时钟周期,因此更有可能做你想做的事。

4) 小问题:您对“i”的声明是多余的,实际上被循环语句创建的新隐式“i”隐藏了。这种隐式声明比显式声明更安全和更好,因为它显式地从循环边界获取其类型。想象一下for(int i; i<= 100000; i++)int是 16 位类型时会发生什么......

于 2013-06-16T12:04:54.183 回答
0

bcdout 是一个信号,您正在使用变量赋值运算符 := 与它

换行

bcdout := bcd;

bcdout <= bcd;

我没有尝试编译以查看是否还有其他问题,但这应该可以回答您的问题。

于 2013-06-16T10:35:33.097 回答
0

呵呵,奇怪。您是否尝试过使 bcd 成为信号而不是变量?

但是,我认为您的主要问题是您正在尝试使用 for 循环和顺序逻辑以“软件”方式编写 VHDL。这通常不是您编写硬件描述的方式。您应该使用涉及并发分配的组合逻辑或涉及在时钟上升沿执行操作的顺序逻辑。看来您要实现的是组合电路。在这种情况下,您应该为每个十进制数字编写单独的并发分配。查看http://www.csee.umbc.edu/portal/help/VHDL/concurrent.html了解并发信号分配的一些示例。您可能希望使用选定或条件信号分配。

于 2013-06-15T22:13:55.910 回答