2016-05-04 7 views
0

Soweit ich in VHDL verstehe, ist es nicht möglich, Port-Zuordnungen zu Komponenten innerhalb eines Prozesses zu haben. und ich war neugierig, ob es einen alternativen Weg gibt, sich einem bedingten Szenario zu nähern.Alternativer Weg für Port Map in Bearbeitung?

hier ein Beispiel von meinem Rechner VHDL-Code, die ich aktuell arbeite:

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; 

das Hauptproblem, dass ich nicht wirklich meinen Geist wickeln kann um ist, wie mein Addiererkomponente unter bestimmten Umständen zu verwenden (die If/Else-Bedingungen).

+2

Bedenken Sie, dass Sie keine Hardware magisch erscheinen und verschwinden nach Belieben ... FPGAs sind cool, aber nicht so cool ... so denken, entlang der Linien den Addierer immer zur Verfügung zu haben, aber bedingt seine Ausgabe zu verwenden oder zu ignorieren. –

+0

@BrianDrummond Nun, es sei denn, Sie wollen in teilweise Rekonfiguration gehen. ;) – PlayDough

Antwort

1

Wie @BrianDrummond sagt, können Sie nicht Hardware magisch erscheinen und verschwinden nach Belieben. Sie können nicht entscheiden, ob ein Stück Hardware existiert und nicht existiert, basierend auf einigen Eingaben an die Hardware. Anstatt also, müssen Sie die Hardware einmal instanziiert und dann zu kontrollieren, was eingegeben wird, um es ist:

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? 

So können Sie sehen, habe ich zwei neue Signale erklärt haben L und R und ich bin mit Ihrem Prozess zu steuern Was treibt sie an? Der Block ADD fügt dann eine Kombination von R0, R1, R2 und R3 hinzu.

Ich habe Ihre Frage unten beantwortet, aber ich sehe viele andere Probleme in Ihrem Code, obwohl es eine ganze Menge davon gibt und ich nur einen kurzen Blick darauf gab. Um erscheinen sie nicht in der Reihenfolge der Schwere:

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

Denken Sie sehr sorgfältig, warum Sie diese Signale werden initialisiert. Dies könnte in einem FPGA funktionieren, aber (aus einem IC-Design-Hintergrund kommend) scheint es gefährlich, sich auf die Initialisierung von Signalen zu verlassen.

ii) Sie vermissen den Instanznamen (streng ein Label) für Ihren Decoder:

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

Es sollte so etwas sein:

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

iii) Sie sollten wirklich verwenden benannte Zuordnung in Ihren Port-Maps.Statt:

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

tun:

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

iv) Ihr Prozess keine Vorlage für einen synthetisierbaren sequenziellen Prozess paßt:

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 

Hier ist eine Vorlage für einen sequentiellen Prozess ist mit einem asynchronen Reset:

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;   

Also, ENABLE sollte nicht in Ihrer Empfindlichkeitsliste sein; die erste Zeile des Prozesses sollte sein:

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

Sie sollten testen, den absoluten Wert zurückgesetzt, nicht suchen eine steigende Flanke:

calc: process (Clock, RESET) 

Sie sollten für rising_edge(Clock) das ENABLE Signal nach dem Test testen . Und Sie brauchen nicht alle diese Klammern. also nicht so:

if (rising_edge(RESET)) then 

dies:

if RESET = '1' then 

Diese Linie ist redundant:

elsif (Clock = '1') then 

v) Sie nicht beiden Flanken des Taktes testen werden. Dies ist kein synchrones Design. Sie können nicht beide Kanten in einem einzigen Prozess testen. Das ist nicht einmal synthetisch. Dies muss gehen:

elsif (falling_edge(Clock)) then 

vi) Ich bin besorgt, dass Sie R0-R3 früher im Prozess fahren und dann später ihre Werte verwenden. Es ist schwierig, genau Ihre Konstruktionsabsicht zu sehen, aber ich vermute, das wird nicht funktionieren:

In VHDL Signale erst zu einem Prozess aktualisiert aussetzt. Wenn Sie versuchen, ein zuvor zugewiesenes Signal in einem Prozess zu verwenden, erhalten Sie den zuvor zugewiesenen Wert.

Allgemeine

Ich schlage vor, Sie Ihr Design in viele kleinere Prozesse zu brechen. Haben Sie eine klare Idee für jede Art von Hardware, die Sie für jeden erwarten. Jede hat eine bestimmte Funktion, zB Multiplexen der Eingänge zu ADD block. Beispiel:

  • Ist der Prozess sequenzielle oder kombinatorische Logik?

  • ist der Reset asynchron oder synchron?

  • Was sind die Eingänge?

  • Was sind die Ausgänge?

Und dann wählen Sie die entsprechende Vorlage. Ich habe einen für einen sequentiellen Prozess mit einem asynchronen Reset gegeben. Hier ist eine für einen sequentiellen Prozess ohne einen asynchronen Reset:

process(clock) -- nothing else should go in the sensitivity list 
begin 
    -- never put anything here 
    if 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; 
+0

Vielen Dank für Ihr Feedback. Ich werde das definitiv ausprobieren. Ich bin jetzt nicht mit Vhdl vertraut, und als Sie meinen Code durchschauten, ist es eher C/C++ Sprache formatiert (weil ich mit dieser Sprache mehr vertraut bin) als tatsächliche vhdl (ich weiß, dass sie vollständig sind verschiedene Sprachen). – Jon

+0

@ Jon Absolut grundlegend anders. C/C++ sind _Software-Sprachen_; VHDL ist eine Hardware-Beschreibungssprache. Sie beschreiben Hardware, die keine Software schreibt. –