2016-07-11 16 views
1

これは初めての投稿です。できるだけ具体的にしようとします。汎用VHDLコードのアドレス指定方法にForループを使用する

私が投稿しようとしているコードの部分では、私がコメントした"ケース" -expressionのコードを一般的な方法で実装しようとしています。このコードは、より大きな実装の一部であり、私はこのコードで現在使用されている信号のみを保持しています。

そうなことは、私は一般的なアドレスバス「BUS_A」に入力して来るものに従うことを「親族」「DIN」私の出力を望んでいることを正しい言葉(2あります「0122」)「kin_2」「din_2」は、その時点で「bus_di」の値で入力する必要があります。

ここに私の例では、私は各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ループ

私が理解から、問題は「Forループ」を使用することにし、私が想定したものからですVHDLが次の式を変換できないようにする必要があります。

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

実際の回路への変換はできません。

私の仮説は正しいですか? この問題を解決する方法や、私の答えを見つけるためにどこを見て/読むべきかについての提案は、本当に役に立つでしょう!

+0

範囲 'n-1 downto n'は空の範囲です:ベクトル内の部分範囲として使用され、要素のないベクトルを記述します。しかし、それだけでは致命的なエラーではありません。そこに幅の不一致に関するメッセージがありますか? –

+0

@BrianDrummond あなたはその範囲について正しいです!私はエラーメッセージの最初に再度チェックしていました。最初のエラーは青色で表示されていました: **致命的:(vsim-3420)配列の長さが一致しません。左は0(127 downto 128(ヌル配列))です。右は16(15 downto 0)です** ** 2番目の "int_add"に "+2"を追加して修正しました。 ** kin_2((8 *(N-int_add)-1)downto 8 *(N-(int_add + 2)))<= bus_di; ** 私は本当に眠っているに違いない。今のコードは魅力のように機能します。どんな最適化やアドバイスも歓迎されます!ありがとうございました! –

答えて

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; 
0

私はU.Martinez-コラルはねじれのビットとしていた同じ考えを持っていた:

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; 

これが原因組合の不足のためにKの各便利値について生成する声明を必要としますVHDLでこれは醜い部分です。

それ以外の場合は、ビット(要素インデックス)の範囲を使用しないことです。

と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

注意をそのI追加trig_wrのデフォルト値ないときは、力を使って

補遺

U.マルティネス・コラルは、我々が発生for文の使用を示唆しながら、指数演算を行うことで、一般的に悪いです再び実証し、コメントしています。

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; 

それは同じ波形を生成します(IEEE STD 1076年から2008年、11.8文の生成)

これは、ループ境界が元の質問でコメントアウトcase文に一致するように修正してメソッドを示していますテストベンチ。

+0

私はあなたが言及した 'union'としてfor-generateを使うことができると思います:' UNION:for x in K downto 0 generate kin(N *(x + 1)-1 downto N * x)<= kin_2(バツ);din(N *(x + 1)-1 downto N * x)<= din_2(x); end generate; '。 –

+1

アイデアはスライスの計算を避けることでしたが、forスキームの生成ステートメントは精巧な時間計算になり、わずかな問題を除いて動作するように見えます。K downto 0はdinとkin(K - 1 downto 0?)の9スライスです。また間違ったエンディアン(OPのオリジナルのコメントされた事例を<= kin_2(K - 1 - x)にする必要がありますか? (私たちは一般的に、このような抽象化を適用すると弱いです。おそらく、設定されたソリューションを短縮して一般化するために、右側の構造が必要です)。 – user1155120

関連する問題