2016-05-04 16 views
0

vhdlの私の理解では、プロセス内のコンポーネントにポートマッピングを持たせることはできません。条件付きのシナリオにアプローチする別の方法があるかどうか不思議でした。ここ処理中のポートマップの代替方法はありますか?

は、私が現在働いている私の電卓のVHDLコードの例です:私は本当に周りに私の心をラップすることはできません

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


-- OP CODE TABLE -- 
-- 00 : LOAD -- 
-- 01 : ADD/SUB -- 
-- 10 : Print-- 
-- 11 : BEQ -- 

-- li - RS Values -- 
-- 00 : R0 -- 
-- 01 : R1 -- 
-- 10 : R2 -- 
-- 11 : R3 -- 


-- //  add  | op, rs, rd, rt  // 
-- //  sub  | op, rs, rd, rt  // 
-- //  li  | op, rs, immediate // 
-- //  beq  | op, rs, rd, zero  // 
-- //  print | op, rs, zero, one // 


-- Current Problems -- 

-- need variables? 
-- dont know what to do with numInst 

entity Calculator is 

port (

    Clock  : in std_logic; 
    numInst  : in std_logic_vector (7 downto 0); 
    --Max Value of PC? 8 bits 
    Instruction : in std_logic_vector (7 downto 0); 
    --8 bit instruction 
    PC   : out std_logic_vector (7 downto 0); 
    --8 bit output, used to retrieve next instruction 
    PRINTER  : out std_logic_vector (7 downto 0); 
    --8 bit output is set to value of register when instruction display is executed 
    ENABLE  : in std_logic; 
    --when high, instruction execute, when low, hold-no instruction executed 
    RESET  : in std_logic 
    --on rising edge, reset register value to 0, restart excution of calculator 

); 

end Calculator; 

architecture Behavorial of Calculator is 

component ADD is 

port (

    A : in std_logic_vector(7 downto 0); 
    B : in std_logic_vector(7 downto 0); 
    Carry : out std_logic; 
    Sum : out std_logic_vector(7 downto 0) 

); 
end component; 


component decode is 

port (

    instr : in std_logic_vector (7 downto 0); 
    op : in std_logic_vector (1 downto 0); 
    rs : in std_logic_vector (1 downto 0); 
    rd : out std_logic_vector (1 downto 0); 
    rt : out std_logic_vector (1 downto 0) 

); 
end component; 

--need variable or signal to store opcode 
--maybe need variable to store values identifier of rs, rt, rd 
--random comment for something else...idk 
--maybe we dont need a separate register vhdl file, make variable? 

signal op, rs, rt, rd: std_logic_vector(1 downto 0):=(others=>'0'); 
signal immediate, AddOut: std_logic_vector(7 downto 0):=(others=>'0'); 
signal carrybit: std_logic; 
--make register signals? R0, R1, R2, R3 
signal R0, R1, R2, R3: std_logic_vector (7 downto 0) := "00000000"; 

begin 


--portmap 
decode port map (Instruction, op, rs, rd, rt); 

calc: process (Clock, ENABLE, RESET) 

-- use variables opcode, rs, rt, rd to break up Instruction 


begin 

    if (ENABLE = '0') then 

     --nothing, calculator is disabled 

    else --ENABLE at 1 



     if (rising_edge(RESET)) then 

      PC <= "00000000"; -- restart execution 
      op <= "00"; 
      rs <= "00"; 
      rt <= "00"; 
      rd <= "00"; 

      --registers go to 0 

     elsif (rising_edge(Clock)) then 

      --   


     elsif (Clock = '1') then 
      if (op = "00") then 
      --maybe can be used to load values into registers 

       if(rd(1)='1') then 
        immediate(7 downto 4):='1'; 
        immediate(3 downto 2)<= rd; 
        immediate(1 downto 0)<= rt; 
       else 
        immediate(7 downto 4):='0'; 
        immediate(3 downto 2)<= rd; 
        immediate(1 downto 0)<= rt;   
       end if; 


      --PC = PC + 1 
      elsif (op = "01") then --add 

       if(rs = "00") then 
        if(rt = "00") then 
         addi00: ADD port map(R0,R0,carrybit,AddOut); 
        elsif(rt = "01") then 
         addi01: ADD port map(R0,R1,carrybit,AddOut); 
        elsif(rt = "10") then 
         addi02: ADD port map(R0,R2,carrybit,AddOut); 
        else 
         addi03: ADD port map(R0,R3,carrybit,AddOut); 
        end if; 
       elsif(rs = "01") then 
        if(rt = "00") then 
         addi10: ADD port map(R1,R0,carrybit,AddOut); 
        elsif(rt = "01") then 
         addi11: ADD port map(R1,R1,carrybit,AddOut); 
        elsif(rt = "10") then 
         addi12: ADD port map(R1,R2,carrybit,AddOut); 
        else 
         addi13: ADD port map(R1,R3,carrybit,AddOut); 
        end if; 
       elsif(rs = "10") then 
        if(rt = "00") then 
         addi20: ADD port map(R2,R0,carrybit,AddOut); 
        elsif(rt = "01") then 
         addi21: ADD port map(R2,R1,carrybit,AddOut); 
        elsif(rt = "10") then 
         addi22: ADD port map(R2,R2,carrybit,AddOut); 
        else 
         addi23: ADD port map(R2,R3,carrybit,AddOut); 
        end if; 
       else 
        if(rt = "00") then 
         addi30: ADD port map(R3,R0,carrybit,AddOut); 
        elsif(rt = "01") then 
         addi31: ADD port map(R3,R1,carrybit,AddOut); 
        elsif(rt = "10") then 
         addi32: ADD port map(R3,R2,carrybit,AddOut); 
        else 
         addi33: ADD port map(R3,R3,carrybit,AddOut); 
        end if; 
       end if; 
       --use component of adder vhdl file? 
       --PC = PC + 1 ? 


       --use adder (subtractor) component 
       --PC = PC + 1 ? 

      elsif (op = "10") then 

      -- need rs, rt, rd, variable? 

        if (rs = "00") then 

         PRINTER <= R0; 
         --insert print code here 
         --PC = PC + 1 -- to continue to next instruction 

        elsif (rs = "01") then 

         PRINTER <= R1; 
         --insert print code here 
         --PC = PC + 1 -- to continue to next instruction 

        elsif (rs = "10") then 

         PRINTER <= R2; 
         --insert print code here 
         --PC = PC + 1 -- to continue to next instruction 
        else --(rs = "11") then 

         PRINTER <= R3; 
         --insert print code here 
         --PC = PC + 1 -- to continue to next instruction  

        end if; 


      elsif (op = "11") then --beq 

       --if (register1 != register2) then 

         --PC <= PC + 1; 

       --else 

         --PC <= PC + 2; 

       --end if; 

      end if; 

     end if; 

     elsif (falling_edge(Clock)) then 

      if (op = "00") then 

       if (rs = "00") then 

        R0 <= immediate; 

       elsif (rs = "01") then 

        R1 <= immediate; 

       elsif (rs = "10") then 

        R2 <= immediate; 

       else --rs = "11" 

        R3 <= immediate; 

       end if; 

      elsif (op = "01") then 

       if (rd = "00") then 

        R0 <= AddOut;--output of adder; 

       elsif (rd = "01") then 

        R1 <= AddOut;--output of adder; 

       elsif (rd = "10") then 

        R2 <= AddOut;--output of adder; 

       else --rd = 11 

        R3 <= Addout;--output of adder; 

       end if; 

      end if; 

     end if; 

    end if; 

end process calc; 

end architecture Behavorial; 

主な問題は、(特定の状況下で、私の加算コンポーネントを使用する方法ですif/else条件)。

+2

ハードウェアを魔法のように表示させたり消したりすることはできないと考えてください... FPGAはクールだがクールではない...ラインに沿って考える加算器が常に存在するが、条件付きではその出力を使用または無視する。 –

+0

@BrianDrummondあなたがパーシャルリコンフィギュレーションを取得しない限り、まあです。 ;) – PlayDough

答えて

1

@BrianDrummondによれば、ハードウェアを魔法のように表示させて非表示にすることはできません。ハードウェアへの入力に基づいてハードウェアが存在するかどうかを判断することはできません。だから、代わりに、あなたは一度ハードウェアをインスタンス化し、それに入力されているかを制御する必要があります。だから、

signal L, R : std_logic_vector (7 downto 0); 

-- snip 

addi: ADD port map(L,R,carrybit,AddOut); -- here is the ADD instance 

calc: process (Clock, ENABLE, RESET) 

-- snip 

     --PC = PC + 1 
     elsif (op = "01") then --add 

      if(rs = "00") then 
       if(rt = "00") then 
        L <= R0; R <= R0; 
       elsif(rt = "01") then 
        L <= R0; R <= R1; 
       elsif(rt = "10") then 
        L <= R0; R <= R2; 
       else 
        L <= R0; R <= R3; 
       end if; 
      elsif(rs = "01") then 
       if(rt = "00") then 
        L <= R0; R <= R0; 
       elsif(rt = "01") then 
        L <= R1; R <= R1; 
       elsif(rt = "10") then 
        L <= R1 R <= R2; 
       else 
        L <= R1; R <= R3; 
       end if; 
      elsif(rs = "10") then 
       if(rt = "00") then 
        L <= R2; R <= R0; 
       elsif(rt = "01") then 
        L <= R2; R <= R1; 
       elsif(rt = "10") then 
        L <= R2; R <= R2; 
       else 
        L <= R3; R <= R3; 
       end if; 
      else 
       if(rt = "00") then 
        L <= R3; R <= R0; 
       elsif(rt = "01") then 
        L <= R3; R <= R1; 
       elsif(rt = "10") then 
        L <= R3; R <= R2; 
       else 
        L <= R3; R <= R3; 
       end if; 
      end if; 
      --use component of adder vhdl file? 

、私は二つの新しい信号LRを宣言していると私は制御するためにプロセスを使用しています見ることができます何がそれらを運転している。 ADDブロックは、R0,R1,R2およびR3のいくつかの組み合わせを追加します。

私はあなたに以下の質問に答えましたが、コードには他にも多くの問題がありますが、かなりの数がありますが、私は一目瞭然です。ために、彼らは深刻の順に、表示されません:あなたはこれらの信号を初期化している理由

I)signal R0, R1, R2, R3: std_logic_vector (7 downto 0) := "00000000";

非常に慎重に考えてください。これはFPGAで動作するかもしれませんが、(IC設計の背景から)信号を初期化することに頼るのは危険です。

II)あなたは、あなたのデコーダのインスタンス名(厳密にラベル)が不足している:

decode port map (Instruction, op, rs, rd, rt); 

それはのようなものでなければなりません:III)あなたが本当に使うべき

deci : decode port map (Instruction, op, rs, rd, rt); 

あなたのポートマップには名前が付いています。代わりに:

deci : decode port map (Instruction, op, rs, rd, rt); 

行います

deci : decode port map (instr => Instruction, op => op, rs => rs, rd = rd, rt => rt); 

IV)あなたのプロセスは、合成可能逐次プロセスのための任意のテンプレートに適合していません。ここで

calc: process (Clock, ENABLE, RESET) 
begin  

    if (ENABLE = '0') then  

    else --ENABLE at 1 

     if (rising_edge(RESET)) then 

     elsif (rising_edge(Clock)) then 

     elsif (Clock = '1') then 

は順次処理するためのテンプレートです非同期リセット付き:

process(clock, async_reset) -- nothing else should go in the sensitivity list 
begin 
    -- never put anything here 
    if async_reset ='1' then -- or '0' for an active low reset 
     -- set/reset the flip-flops here 
     -- ie drive the signals to their initial values 
    elsif rising_edge(clock) then -- or falling_edge(clock) 
     -- put the synchronous stuff here 
     -- ie the stuff that happens on the rising or falling edge of the clock 
    end if; 
    -- never put anything here 
end process;   

したがって、ENABLEは機密リストには含めないでください。あなたのプロセスの最初の行でなければなりません:

calc: process (Clock, RESET) 

あなたはrising_edge(Clock)ための試験後ENABLE信号をテストする必要があります。

 elsif (rising_edge(Clock)) then 
      if (ENABLE = '0') then  

あなたは立ち上がりエッジを探して、リセットの絶対値をテストする必要がありません。そしてあなたはそれらのカッコをすべて必要としません。すなわちないこの:

if (rising_edge(RESET)) then 

この:

if RESET = '1' then 

この行は冗長です:

elsif (Clock = '1') then 

V)あなたはは、クロックの両エッジをテストするべきではありません。これは同期設計ではありません。 は、単一のプロセスで両方のエッジをテストできません。それは合成可能でさえありません。これは行く必要があります:

elsif (falling_edge(Clock)) then 

VI)私はあなたが以前のプロセスでR3R0を駆動し、後でその値を使用していることを懸念しています。まさにあなたの設計意図を確認することは困難であるが、私は、これは動作しません疑う:

VHDLで信号がを中断し工程までは更新されません。以前にプロセスで割り当てられた信号を使用しようとすると、以前に割り当てられた値が取得されます。

一般

私はあなたが多くの小さなプロセスにあなたのデザインを破る示唆しています。それぞれのハードウェアの種類を明確にしてください。それぞれが特定の機能を実行するようにしてください。例えば、入力をADD blockに多重化してください。たとえば、次の点を考慮してください。

  • プロセスは順次または組み合わせロジックですか?

  • はリセットされた非同期または同期ですか?

  • 入力とは何ですか?

  • 出力は何ですか?

次に、適切なテンプレートを選択します。私は、非同期リセットを伴うシーケンシャルプロセスのために1つを与えました。

+0

フィードバックいただきありがとうございます。私は間違いなくこれを試してみます。私は今ではvhdlにはあまり慣れていないし、私のコードを垣間見ると、実際のVHDLではなくC/C++言語にもっとフォーマットされている(私はそれらが完全であることを知っている異なる言語)。 – Jon

+0

@Jonまったく根本的に異なる。 C/C++は_software languages_です; VHDLは_ハードウェア記述言語です。ハードウェアを記述していないハードウェアについて説明しています。 –

関連する問題