我的VHDL波形图是错误的

时间:2014-10-19 04:32:38

标签: vhdl diagram waveform

我目前正在研究一些VHDL代码,使用DesignWorks 5程序制作CPU。我的电路波形图没有输出它应该的东西。我的所有代码编译都很好。有没有什么办法解决这一问题?我觉得我错过了一些小而愚蠢的东西。提前感谢您的帮助。 (我没有足够的声望发布2个链接!)

以下是电路的波形: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;

1 个答案:

答案 0 :(得分:0)

首先,您应该切换到使用更多标准逻辑在时钟边缘运行SEQ,尤其是如果您想要合成它。如果你有任何来自导入的包(现在逃避我的记忆),那么像“如果rising_edge(clk)那么”是很好的,否则就像“if clk'event AND clk ='1'那样”。我也强烈推荐命名状态,而不是使用位向量来提高可读性。

在CALC中,您指定的唯一输出信号是cs。并为它分配一个仅在状态0001中分配的变量的值。因此它将从X开始,并且(可能在某个时刻)永远转换为'1'。

两个块都读取opc,所以除非你有一些外部设备同时驱动(这与你的图表不匹配),这是错误的。看起来CALC应该驱动opc,但它需要A)使它成为输出端口,B)实际上为它分配一些东西(我猜测变量opc_val是一个很好的候选者)。

如果你来自传统的编程语言,我可以理解为什么你会如此喜欢变量,但如果你试图避免使用它们,你会更开心。大多数仿真工具为查看变量提供了有限的支持,并且编写VHDL非常容易,因为它们允许您根据语句的顺序在您的逻辑中意外地放置长依赖链,因此可以将VHDL编译成可变的变量。因此,如果可能的话,我会尽可能多地摆脱这些变量并将它们变成信号。如果你想在相同的增量周期中读取值,你只需要变量,并且你几乎从不这样做(如果不是分配一个名为cs_val的变量然后将其分配给信号cs,你刚刚分配给cs,它根本不会改变你的代码的含义。)