0

4つの押しボタンを入力として使用し、3つの7セグメントLEDディスプレイを出力として使用したいと思います。2つのプッシュボタンは、16のRAMロケーションを上下に移動する必要があります。他の2つは、現在表示されているメモリ位置の内容をインクリメントおよびデクリメントする必要があります。1つの7セグメントディスプレイには現在のアドレス(0–F)が表示され、他の2つのディスプレイにはその場所の内容が16進数(00–FF)で表示されます。これはこれを試みるための私のコードです(私はまだ表示を実装していません):

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

entity raminfr is
    port (
        clk : in std_logic;
        we : in std_logic;
        do : out unsigned(7 downto 0)
    );
end raminfr;

architecture rtl of raminfr is

type ram_type is array (0 to 15) of unsigned(7 downto 0);
signal RAM : ram_type;
signal read_a : unsigned(3 downto 0);
signal a : unsigned(3 downto 0);
signal di : unsigned(7 downto 0);
signal clock : std_logic;
signal key : std_logic_vector(3 downto 0);
begin
  U1: entity work.lab1 port map (
    clock =>clock,
    key => key,
    register_counter => a,
    value_counter => di
  );
process (clk)
begin
    if rising_edge(clk) then
        if we = '1' then
            RAM(to_integer(a)) <= di;
        end if;
        read_a <= a;
    end if;
end process;
do <= RAM(to_integer(read_a));
end rtl;

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

entity lab1 is
    port(
        clock : in std_logic;
        key : in std_logic_vector(3 downto 0); 
        value_counter   : buffer unsigned(7 downto 0) ;
        register_counter : buffer unsigned(3 downto 0) 
        );
end lab1;

architecture up_and_down of lab1 is
    signal value_in_ram : unsigned(7 downto 0);
    signal clk : std_logic;
    signal we : std_logic;
        begin
        U1: entity work.raminfr port map (
            do=>value_in_ram,
            clk=>clk,
            we=>we
        );
    process(clock, value_counter, register_counter)
        begin
            if rising_edge(clock) then
                if (key(3)='0' and key(2)='0' and key(1)='1' and key(0)='0') then
                    value_counter <= value_counter + "1";   
                elsif (key(3)='0' and key(2)='0' and key(1)='0' and key(0)='1') then  
                    value_counter <= value_counter - "1";   
                elsif (key(3)='1' and key(2)='0' and key(1)='0' and key(0)='0') then
                    register_counter<= register_counter + "1";
                    value_counter <= value_in_ram;
                elsif (key(3)='0' and key(2)='1' and key(1)='0' and key(0)='0') then
                    register_counter<= register_counter - "1";
                    value_counter <= value_in_ram;
                end if;
            end if;
    end process;
end architecture up_and_down;

これをコンパイルしようとすると、次のエラーが何度も繰り返されます。

Error (12051): Project too complex: hierarchy path is too long
Error (12052): Entity "lab1" is instantiated by entity "raminfr"
Error (12052): Entity "raminfr" is instantiated by entity "lab1"

これは明らかに、各エンティティを他のエンティティにポートマップしたためですが、達成したいことを達成する他の方法がわかりません。誰かが代替案を提案できますか?

4

1 に答える 1

2

あなたが何をしたいのかがあまり明確ではないので、これは推測です。問題は設計の1つであるように思われます。最終結果がどうなるかはよくわかっていますが、目標を達成するために最も簡単な方法で相互作用するコンポーネントにそれを分解する方法は明確ではありません。

この推測は、「raminfr」のアクティブなコードが、侵入した他のものとは無関係にデータを格納およびロードするという事実に基づいています。

したがって、「raminfr」は、他のものを使用せずに、単なるメモリコンポーネントとしてクリーンアップすることをお勧めします。次に、キーを処理し、正しいレジスタからの値を格納および表示する「lab1」コンポーネントに埋め込むことができます。また、メモリが必要な他の場所で再利用することもできます。

それでは、raminfrを見てみましょう。

entity raminfr is
    port (
        clk : in std_logic;
        we : in std_logic;
        do : out unsigned(7 downto 0)
    );
end raminfr;

クロック、書き込みイネーブル入力、およびデータ出力があります。しかし、不思議なことに、アドレスやデータの入力はありません!さて、メモリは非常に標準的な「デザインパターン」であるため、メモリからの逸脱はおそらくお勧めできません。それらを追加しましょう...

entity raminfr is
    port (
        clk  : in std_logic;
        we   : in std_logic;
        addr : in unsigned(3 downto 0);
        di   : in  unsigned(7 downto 0);
        do   : out unsigned(7 downto 0)
    );
end raminfr;

メモリパターンの一部のバリアントには他の機能があります。読み取りイネーブル、出力イネーブル、個別の読み取りクロックと書き込みクロックなどがありますが、この単純な方法でここで実行できます。

ジェネリックを使用してサイズをカスタマイズし、それに合わせてデータとアドレスバスの幅を変更することもできます。これにより、はるかに便利になり、類似しているが異なるモジュールの急増を防ぐことができます...

それに合わせてアーキテクチャをクリーンアップしましょう。

architecture rtl of raminfr is
   type ram_type is array (0 to 15) of unsigned(7 downto 0);
   signal RAM    : ram_type;
   signal read_a : unsigned(3 downto 0);
begin
process (clk)
...
end process;
do <= RAM(to_integer(read_a));
end rtl;

これで、「lab1」モジュールでインスタンス化して、新しいポートを接続できます。

    U1: entity work.raminfr port map (
        addr => register_counter,   -- was "a", typo
        di   => value_counter,
        do   => value_in_ram,
        clk  => clk,
        we   => we
    );

そして、lab1の残りの部分にサポートする変更を加えます。

これが唯一の合理的な分解ではありません。「lab1」を独自のストレージのない単純なコンポーネントにして、他の必要な信号をポートとして引き出すこともできます。次に、アーキテクチャがlab1とraminfrを相互接続する3番目の「トップレベル」エンティティが必要になります。

于 2013-01-26T10:36:29.110 に答える