2014-10-19 108 views
2

我目前正在使用程序DesignWorks 5製作一些CPU的VHDL代碼。我的電路波形圖並不是輸出它應該輸出的內容。我所有的代碼編譯得很好。有沒有什麼辦法解決這一問題?我覺得我錯過了一些小而愚蠢的東西。預先感謝您的幫助。 (我沒有足夠的聲譽後2個鏈接!)我的VHDL波形圖是錯誤的

下面是電路的波形應該是什麼樣子:imgur.com/IBtoFuO

What the waveform should look like

這裏是我的波形是什麼顯示:imgur.com/rcRTrLR

what my waveform is showing

下面是該CPU的樣子:imgur.com/Ek1G3rZ

What the CPU looks like

下面是狀態機圖的樣子:imgur.com/AeCaPof

what the state mchine diagram looks like

我在每個3個實體的獨立文件中的代碼。 SEQ是我的狀態轉換,CALC是我聲明的輸出轉換,M是我提供的內存。

這是我的狀態轉換的代碼:

library IEEE; 
use IEEE.std_logic_arith.all; 
use IEEE.std_logic_1164.all; 

--Finish Entity Definition 
entity SEQ is 
    port(clk, st, lt, eq : in std_logic; 
     opc : in std_logic_vector(11 downto 9); 
     rdy : in std_logic; 
     new_state : out std_logic_vector(3 downto 0)); --entity transfers over 
end SEQ; 

architecture behav of SEQ is 
begin 
--state transition process 
    process is 
    variable curr_state : std_logic_vector(3 downto 0) := "1101"; 
    begin 
    if clk = '1' then 
    case curr_state is 
     when "0000" => curr_state := "0001"; 
     when "0001" => curr_state := "0010"; 
     when "0010" => curr_state := "0011"; 
     when "0011" => curr_state := "0100"; 
     when "0100" => 
      if opc = "000" then curr_state := "1101"; 
      elsif opc = "001" then curr_state := "0101"; 
      elsif opc = "010" then curr_state := "0110"; 
      elsif opc = "011" then curr_state := "0111"; 
      elsif opc = "100" then curr_state := "1000"; 
      elsif opc = "101" then curr_state := "1001"; 
      elsif opc = "110" then curr_state := "1010"; 
      elsif opc = "111" then curr_state := "1011"; 
      end if; 
     when "0101" => curr_state := "0001"; 
     when "0110" => curr_state := "0001"; 
     when "0111" => curr_state := "0001"; 
     when "1000" => curr_state := "0001"; 
     when "1001" => 
      if rdy = '1' then curr_state := "0001"; 
      elsif rdy = '0' then curr_state := "1001"; 
      end if; 
     when "1010" => 
      if eq = '1' then curr_state := "1100"; 
      elsif eq = '0' then curr_state := "0001"; 
      end if; 
     when "1011" => 
      if lt = '1' then curr_state := "1100"; 
      elsif lt = '0' then curr_state := "0001"; 
      end if; 
     when "1100" => curr_state := "0001"; 
     when "1101" => 
      if st = '1' then curr_state := "1101"; 
      elsif st = '0' then curr_state := "0000"; 
      end if; 
    end case; 
    wait on clk; 
    new_state <= curr_state; 
    end if; 
    end process; 
end behav; 

這是我的斷言輸出代碼:

library IEEE; 
use IEEE.std_logic_arith.all; 
use IEEE.std_logic_1164.all; 

--Entity Definition 
entity CALC is 
    port(clk, cs, r, req, lt, eq : in std_logic;   
      new_state : in std_logic_vector(3 downto 0); 
      opc : in std_logic_vector(11 downto 9); 
      addr : in std_logic_vector(8 downto 0); -- 2^9 
      d0 : in std_logic_vector(11 downto 0); 
      d1 : out std_logic_vector(11 downto 0)); --ignore stuff on arrows 
end CALC; 

architecture behav of CALC is 
type memory is array(0 to 7) of std_logic_vector(11 downto 0); 
begin 
--Asserted output process 
    process is 
    variable curr_state : std_logic_vector(3 downto 0) := "1101"; 
    variable cs_val, r_val, req_val, lt_val, eq_val: std_logic; 
    variable opc_val:std_logic_vector(11 downto 9); 
    variable IR: std_logic_vector(11 downto 0); 
    variable i, j, k, tmp1 , tmp2, value, displ : integer; 
    variable R : memory; 
    variable PC, addr_val : std_logic_vector(8 downto 0); 
    variable dummy : std_logic_vector(5 downto 0); --Ignore this 
    begin 
     case new_state is 
     when "0000" => PC := "000000000"; 
     when "0001" => addr_val := PC; cs_val := '1'; r_val := '1'; 
     when "0010" => IR := d0; 
         PC := PC + "000000001"; 
     when "0011" => opc_val := IR(11 downto 9); 
         i := to_integer(IR(8 downto 6)); 
         j := to_integer(IR(5 downto 3)); 
         k := to_integer(IR(2 downto 0)); 
         value := to_integer(IR(8 downto 3)); 
         displ := to_integer(IR(8 downto 3))-1; 
     when "0100" => if k = 1 then eq_val := '1'; 
         else eq_val := '0'; 
         end if; 
         if k = 2 then lt_val := '1'; 
         else lt_val := '0'; 
         end if; 
     when "0101" => tmp1 := to_integer(R(i)); 
         tmp2 := to_integer(R(j)); 
         k := (tmp1 + tmp2); 
     when "0110" => tmp1 := to_integer(R(i)); 
         tmp2 := to_integer(R(j)); 
         k := (tmp1 - tmp2); 
     when "0111" => if ((i<j) and (i=j)) then k := 1; 
         else k := 0; 
         end if; 
     when "1000" => d1 <= R(k); 
         req_val := '1'; 
     when "1010" => 
     when "1011" => 
     when "1100" => PC := PC + displ; 
     end case; 
     cs <= cs_val; 
     wait on new_state; 
    end process; 
end behav; 
+0

除了使用用於順序邏輯的鎖存器(因此缺少來自靈敏度列表的「rdy」,「opc」,「eq」,「lt」,「st」和「curr_state」)的'seq'之外,它不在案例陳述中有完整的選擇範圍,這是符合VHDL實現的錯誤。 'calc'也有類似的問題。 Designworks 5似乎允許您在不使用包含numeric_std的use語句的情況下使用'to_integer'。一個過分寬鬆的工具實現必然會着色任何幫助。 Korvus指出,缺少一個opc驅動程序,沒有'req'驅動程序(或者放置它被使用)......你的代碼還沒有準備好。 – user1155120 2014-10-19 08:23:14

+0

在執行其他任何操作之前,使用'rising_edge(clk)'和'clk'在其靈敏度列表中將SM變爲標準同步過程。 – 2014-10-19 10:44:18

回答

0

首先,應該切換到使用更標準的邏輯,用於在時鐘邊緣延伸SEQ,特別是如果你想要綜合它。 「如果rising_edge(clk)then」很好,如果你有任何來自導入的包(現在轉義我的記憶),否則就像「if clk'event AND clk ='1 then」。我還強烈推薦命名狀態,而不是使用位向量來提高可讀性。

在CALC中,您分配的唯一輸出信號是cs。並且你給它分配一個變量的值,這個變量只在狀態0001中被賦值。所以它將從X開始,並且(可能在某個時刻)永遠轉換爲'1'。

這兩個塊都讀取opc,所以除非你有一些外部設備驅動兩者(這與你的圖不匹配),這是錯誤的。它看起來像CALC應該驅動opc,但它需要A)使該輸出端口,和B)實際分配的東西(我猜opc_val變量是一個很好的候選人)。

如果你來自傳統的編程語言,我可以理解爲什麼你會喜歡變量,但如果你試圖避免使用它們,你會變得更加快樂。大多數仿真工具對查看變量提供了有限的支持,編寫VHDL可以很容易地將變量綜合到可變的變量中,因爲它們允許您根據語句的順序意外地在邏輯中放置長依賴鏈。所以,如果可能的話,我會擺脫儘可能多的變量,並將它們變成信號。你只需要變量,如果你想在相同的增量週期中讀取數值,而且你幾乎從不這樣做(如果不是分配一個名爲cs_val的變量,然後將它分配給信號cs,而是將它分配給cs,根本不會改變你的代碼的含義)。