在通用VHDL代码中使用“For-Loop”寻址方法

时间:2016-07-11 17:19:57

标签: generics vhdl addressing-mode

这是我第一次发帖,所以我会尽量做到更具体。

在我要发布的代码部分中,我试图以通用方式实现我已注释掉的“Case” - 表达式中的代码。这段代码是更大实现的一部分,我只保留了此代码中当前使用的信号。

所以问题是我希望我的输出“kin”“din”是通用的,并且根据地址总线的输入“bus_a”,寄存器“kin_2”“din_2”的正确字(2字节长)应填充值那时“bus_di”输入。

对于我的例子,我将使用“kin”“din”的原始长度,每个长度为128位。因此,对于128位长度, N = 16 (16 * 8位= 128位)和 K = 8

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

entity stck_if is
    generic (N: integer:=16; K: integer:=8);

    port (  -------------- Clock and Reset
        clk: in std_logic;
        rst: in std_logic;


        bus_a: in std_logic_vector (15 downto 0); -- Address
        bus_di: in std_logic_vector (15 downto 0); --Data In

        kin: out std_logic_vector (8*N-1 downto 0);  
        din: out std_logic_vector (8*N-1 downto 0));    

end stck_if;

architecture stck_if_arch of stck_if is

        signal kin_2: std_logic_vector (8*N-1 downto 0);
        signal din_2: std_logic_vector (8*N-1 downto 0);
        signal encdec_2: std_logic;

        signal trig_wr: std_logic;

        begin

            proc1: process(clk,rst)
                variable int_add: integer:=0;
                variable add: std_logic_vector (15 downto 0);
                variable bit_add: std_logic_vector (15 downto 0);
                begin
                    if rst='1' then
                        encdec_2<='0';  
                        kin_2<=(others =>'0');
                        din_2<=(others =>'0');
                    elsif (clk'event and clk='1') then
                        if (trig_wr = '1') then

                            if (bus_a = "0000000000001100") then
                                    encdec_2 <= bus_di(0);
                            end if;

                            for i in 0 to K-1 loop
                                bit_add:="0000000100000000";
                                int_add:= 2*i;
                                add:=std_logic_vector(to_unsigned(int_add, 16));
                                bit_add:= std_logic_vector(unsigned(bit_add) + unsigned(add));
                                if (bus_a = bit_add) then
                                        kin_2((8*(N-int_add)-1) downto 8*(N-int_add)) <= bus_di;
                                end if;                             
                            end loop;


                            for i in 0 to K-1 loop
                                bit_add:="0000000101000000";
                                int_add:= 2*i;
                                add:=std_logic_vector(to_unsigned(int_add, 16));
                                bit_add:= std_logic_vector(unsigned(bit_add) + unsigned(add));
                                if (bus_a = bit_add) then
                                        din_2((8*(N-int_add)-1) downto 8*(N-int_add)) <= bus_di;
                                end if;                             
                            end loop;   



                            --case bus_a is
                            --  when "0000000000001100"=> encdec_2 <= bus_di(0);    --bus_a = 000C hex
                            --  when "0000000100000000"=> kin_2(127 downto 112) <= bus_di;  --bus_a = 0100 hex
                            --  when "0000000100000010"=> kin_2(111 downto 96) <= bus_di;   --bus_a = 0102 hex
                            --  when "0000000100000100"=> kin_2(95 downto 80) <= bus_di;    --bus_a = 0104 hex
                            --  when "0000000100000110"=> kin_2(79 downto 64) <= bus_di;    --bus_a = 0106 hex                                                                          
                            --  when "0000000100001000"=> kin_2(63 downto 48) <= bus_di;    --bus_a = 0108 hex
                            --  when "0000000100001010"=> kin_2(47 downto 32) <= bus_di;    --bus_a = 010A hex
                            --  when "0000000100001100"=> kin_2(31 downto 16) <= bus_di;    --bus_a = 010C hex
                            --  when "0000000100001110"=> kin_2(15 downto 0) <= bus_di; --bus_a = 010E hex

                            --  when "0000000101000000"=> din_2(127 downto 112) <= bus_di;  --bus_a = 0140 hex
                            --  when "0000000101000010"=> din_2(111 downto 96) <= bus_di;   --bus_a = 0142 hex
                            --  when "0000000101000100"=> din_2(95 downto 80) <= bus_di;    --bus_a = 0144 hex
                            --  when "0000000101000110"=> din_2(79 downto 64) <= bus_di;    --bus_a = 0146 hex                                                                          
                            --  when "0000000101001000"=> din_2(63 downto 48) <= bus_di;    --bus_a = 0148 hex
                            --  when "0000000101001010"=> din_2(47 downto 32) <= bus_di;    --bus_a = 014A hex
                            --  when "0000000101001100"=> din_2(31 downto 16) <= bus_di;    --bus_a = 014C hex
                            --  when "0000000101001110"=> din_2(15 downto 0) <= bus_di; --bus_a = 014E hex
                            --  when others => null;                    
                            --end case;
                        end if;
                    end if;
            end process;



            kin <= kin_2;
            din <= din_2;

end stck_if_arch;

我正在使用 ModelSim PE学生版10.4a 。为了模拟实现的操作,我在ModelSim的命令行中使用以下代码:

restart -f

//clock period 20ns
force -freeze sim:/stck_if/clk 1 0, 0 {10 ns} -r 20


//Activate reset
force -freeze sim:/stck_if/rst 1 0
run

//activate wr
force -freeze sim:/stck_if/trig_wr 1 0

force -freeze sim:/stck_if/rst 0 0
run

force -freeze sim:/stck_if/bus_a 16'h0100 0
force -freeze sim:/stck_if/bus_di 16'h1111 0
run
run


force -freeze sim:/stck_if/bus_a 16'h0102 0
run
run

force -freeze sim:/stck_if/bus_a 16'h0104 0
run
run

force -freeze sim:/stck_if/bus_a 16'h0106 0
run
run

force -freeze sim:/stck_if/bus_a 16'h0108 0
run
run

etc.

尽管代码编译时没有给出任何错误,但在模拟过程中ModelSim会出现以下错误:

  • 由于致命错误无法继续。 HDL呼叫顺序: 停在C:/Modeltech_pe_edu_10.4a/examples/stack.vhd 53 ForLoop loop

根据我的理解,问题在于使用“For Loop”,从我的假设来看,必须是VHDL不能翻译以下表达式:

kin_2((8*(N-int_add)-1) downto 8*(N-int_add)) <= bus_di;

进入实际电路。

我的假设是对的吗? 任何关于如何克服这个问题的想法,或者我应该在哪里寻找/阅读以找到我的答案的任何建议,都会非常有帮助!

2 个答案:

答案 0 :(得分:0)

以下版本应该在功能上与您的版本相同,更短,并且 - 在我的拙见 - 更容易阅读。但是,我不知道合成结果会是什么。我发现很难想象推断的原语在带变量的单进程描述中会是什么。

architecture stck_if_arch of stck_if is
  signal kin_2: std_logic_vector (8*N-1 downto 0);
  signal din_2: std_logic_vector (8*N-1 downto 0);
  signal encdec_2: std_logic;
  signal trig_wr: std_logic;  
begin
  proc1: process(clk,rst)
    variable high: unsigned(9 downto 0);
    variable bid: integer range 0 to N-1;
    variable left, right: integer range 0 to 8*N-1;
  begin
    if rst='1' then
      encdec_2<='0';  
      kin_2<=(others =>'0');
      din_2<=(others =>'0');
    elsif (clk'event and clk='1') then
      if (trig_wr = '1') then

        high := unsigned(bus_a(15 downto 6));
        bid := to_integer(unsigned(bus_a(5 downto 1)));
        left := 16*(8-bid)-1;
        right := 16*(7-bid);

        if bus_a="0000000000001100" then
          encdec_2 <= bus_di(0);
        elsif bus_a(0)='0' then
          if high=4 then
            kin_2(left downto right) <= bus_di;
          elsif high=5 then
            din_2(left downto right) <= bus_di;
          end if;
        end if;

      end if;
    end if;
  end process;

 kin <= kin_2;
 din <= din_2;

end stck_if_arch;

答案 1 :(得分:0)

我有同样的想法,U.Martinez-Corral有点扭曲:

architecture foo of stck_if is
    type N_array is array (0 to K - 1) of std_logic_vector(N - 1 downto 0);
    signal kin_2: N_array;
    signal din_2: N_array;
    signal encdec_2: std_logic;
    signal trig_wr: std_logic := '1'; -- ;  -- FOR TESTING without FORCE
begin

proc1: 
    process(clk,rst)
        variable high: unsigned(9 downto 0);
        variable Kidx: integer range 0 to K-1;
    begin
        if rst = '1' then
            encdec_2 <= '0';  
            kin_2 <= (others => (others => '0'));
            din_2 <= (others => (others => '0'));
        elsif rising_edge(clk) then
            if trig_wr = '1' then
                high := unsigned(bus_a (15 downto 6));
                Kidx := to_integer(unsigned(bus_a(3 downto 1)));
                if bus_a = "0000000000001100" then
                    encdec_2 <= bus_di(0);
                elsif bus_a(0) = '0' then
                    if high = 4 then
                        kin_2(kidx) <= bus_di;
                    elsif high = 5 then
                        din_2(kidx) <= bus_di;
                    end if;
                end if;
            end if;
        end if;
    end process;

UNION:
    if K = 8 generate
        kin <= kin_2(0) & kin_2(1) & kin_2(2) & kin_2(3) & 
               kin_2(4) & kin_2(5) & kin_2(6) & kin_2(7);
        din <= din_2(0) & din_2(1) & din_2(2) & din_2(3) & 
               din_2(4) & din_2(5) & din_2(6) & din_2(7);
    end generate;  -- GENERATE statement for every usable K value

end architecture foo;

由于VHDL中缺少联合,因此需要为K的每个有用值生成一个generate语句。这是丑陋的一部分。

否则,这里的想法是不使用位(元素索引)范围。

对于我们这些不是Modelsim许可证持有者/用户的测试平台:

library ieee;
use ieee.std_logic_1164.all;

entity stck_if_tb is
end entity;

architecture foo of stck_if_tb is
    constant K:     integer := 8;
    constant N:     integer := 16;
    signal clk:     std_logic := '0';
    signal rst:     std_logic;

    signal bus_a:   std_logic_vector (15 downto 0);
    signal bus_di:  std_logic_vector (15 downto 0);

    signal kin:     std_logic_vector (8 * N - 1 downto 0);  
    signal din:     std_logic_vector (8 * N - 1 downto 0);
begin
DUT:
    entity work.stck_if 
        generic map (
            N => N,
            K => K
        )
        port map (
            clk => clk,
            rst => rst,
            bus_a => bus_a,
            bus_di => bus_di,
            kin => kin,
            din => din
        );
CLOCK:
    process
    begin
        wait for 10 ns;
        clk <= not clk;
        if now > 240 ns then
            wait;
        end if;
    end process;
STIMULI:
    process
    begin
        wait for 20 ns;
        rst <= '1';
        wait for 20 ns;
        rst <= '0';
        bus_a <= x"0100";
        bus_di <= x"1111";
        wait for 20 ns;
        wait for 20 ns;
        bus_a <= x"0102";
        wait for 20 ns;
        wait for 20 ns;
        bus_a <= x"0104";
        wait for 20 ns;
        wait for 20 ns;
        bus_a <= x"0106";
        wait for 20 ns;
        wait for 20 ns;
        bus_a <= x"0108";
        wait for 20 ns;
        wait for 20 ns;
        wait;
    end process;
end architecture;

这就是:

stck_if_tb_foo.png

请注意,我在不使用武力时添加了trig_wr默认值。

附录

Ú。 Martinez-Corral评论说,再次证明我们在建议使用for generate语句时一般都不好做索引算术。 (IEEE Std 1076-2008,11.8 Generate statements)

这演示了修正循环边界以匹配原始问题中注释掉的case语句的方法:

UNION: 
    for x in K - 1 downto 0 generate 
        kin(N * (x + 1) - 1 downto N * x) <= kin_2(K - 1 - x); 
        din(N * (x + 1) - 1 downto N * x) <= din_2(K - 1 - x); 
    end generate;

它与测试平台生成相同的波形。