格雷码增量器的VHDL数据流描述

时间:2017-11-05 10:12:52

标签: vhdl behavior dataflow gray-code

我正在尝试使用数据流描述样式编写格雷码增量器的VHDL代码。我不明白如何将行为描述中使用的for循环转换为数据流描述。有什么建议吗?

这是我在行为描述中的工作代码

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

entity graycode is
    Generic (N: integer := 4);
     Port ( gcode : in  STD_LOGIC_VECTOR (N-1 downto 0);
           nextgcode : out  STD_LOGIC_VECTOR (N-1 downto 0));
end graycode;

architecture Behavioral of graycode is
begin

process(gcode)

    variable bcode : STD_LOGIC_VECTOR(N-1 downto 0);
    variable int_bcode : integer;

begin

    for i in gcode'range loop
        if(i < gcode'length - 1) then
            bcode(i) := gcode(i) XOR bcode(i+1);
            else
                bcode(i) := gcode(i);
        end if;
    end loop;

    int_bcode := to_integer(unsigned(bcode));
    int_bcode := int_bcode + 1;
    bcode := std_logic_vector(to_unsigned(int_bcode, N));

    for i in gcode'range loop
        if(i < gcode'length - 1) then
            nextgcode(i) <= bcode(i) XOR bcode(i+1);
            else
                nextgcode(i) <= bcode(i);
        end if;
    end loop;

end process;
end Behavioral;

2 个答案:

答案 0 :(得分:0)

'数据流'意味着'就像它在电路图中看起来'。换句话说,数据流通过实际电路,而不是高级算法描述。因此,展开您的循环并查看您实际描述的内容。从N = 2开始,绘制出展开的电路。您应该得到一个2位输入总线,其中包含一个xor门,然后是一个2位(组合)递增器,接着是一个2位输出总线,其中包含另一个xor门。完成,N = 2。

现在你的问题是推广N.一个显而易见的方法是将你的基本N = 2电路置于generate循环中(是的,这是数据流,因为它只是复制harwdare),并且扩展它。如果你不能这样做,请问另一个问题。

顺便说一句,你的整数递增器很笨重 - 你应该直接递增一个unsigned bcode。

答案 1 :(得分:0)

Dataflow means constructed of concurrent statements using signals.

That means using generate statements instead of loops. The if statement can be an if generate statement with an else in -2008 or for earlier revisions of the VHDL standard two if generate statements with the conditions providing opposite boolean results for the same value being evaluated.

It's easier to just promote the exception assignments to their own concurrent signal assignments:

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity graycode is
    generic (N: natural := 4); -- CHANGED negative numbers wont be interesting
     port ( 
         gcode:      in   std_logic_vector (N - 1 downto 0);
         nextgcode:  out  std_logic_vector (N - 1 downto 0)
    );
end entity graycode;

architecture dataflow of graycode is
    signal int_bcode:     std_logic_vector (N - 1 downto 0);  -- ADDED
    signal bcode:         std_logic_vector (N - 1 downto 0);  -- ADDED
begin

    int_bcode(N - 1) <= gcode (N - 1);
TO_BIN: 
    for i in N - 2 downto 0 generate
        int_bcode(i) <= gcode(i) xor int_bcode(i + 1);
    end generate;

    bcode <= std_logic_vector(unsigned(int_bcode) + 1);

    nextgcode(N - 1) <= bcode(N - 1);
TO_GRAY:
    for i in N - 2 downto 0 generate
        nextgcode(i) <= bcode(i) xor bcode(i + 1);
    end generate;

end architecture dataflow;

Each iteration of a for generate scheme will elaborate a block statement with an implicit label of the string image of i concatenated on the generate statement label name string.

In each of these blocks there's a declaration for the iterated value of i and any concurrent statements are elaborated into those blocks.

The visibility rules tell us that any names not declared in the block state that are visible in the enclosing declarative region are visible within the block.

These mean concurrent statements in the block are equivalent to concurrent statement in the architecture body here with a value of i replaced by a literal equivalent.

The concurrent statements in the generate statements and architecture body give us a dataflow representation.

And with a testbench:

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity graycode_tb is
end entity;

architecture foo of graycode_tb is
    constant N:         natural := 4;
    signal gcode:       std_logic_vector (N - 1 downto 0);
    signal nextgcode:   std_logic_vector (N - 1 downto 0);
    signal bcode:       std_logic_vector (N - 1 downto 0);
begin
DUT:
    entity work.graycode
        generic map ( N => N)
        port map (
            gcode => gcode,
            nextgcode => nextgcode
        );

STIMULi:
    process
    variable gv:        std_logic_vector (N - 1 downto 0);
    variable bv:        std_logic_vector (N - 1 downto 0);
    begin
        wait for 10 ns;
        for i in 0 to 2 ** N - 1 loop  

            bv := std_logic_vector(to_unsigned( i, bv'length));
            gv(N - 1) := bv (N - 1);   
            for i in N - 2 downto 0 loop
                gv(i) := bv(i) xor bv(i + 1);
            end loop;
            gcode  <= gv;
            bcode  <= bv;
            wait for 10 ns;
        end loop;
        wait;
    end process;
end architecture;

We can see the effects of incrementing int_bcode:

graycode_tb.png