我目前正在研究一些VHDL代码,使用DesignWorks 5程序制作CPU。我的电路波形图没有输出它应该的东西。我的所有代码编译都很好。有没有什么办法解决这一问题?我觉得我错过了一些小而愚蠢的东西。提前感谢您的帮助。 (我没有足够的声望发布2个链接!)
以下是电路的波形:imgur.com/IBtoFuO
以下是我的波形显示:imgur.com/rcRTrLR
这是CPU的样子:imgur.com/Ek1G3rZ
以下是状态机图:imgur.com/AeCaPof
我为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 :(得分: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,它根本不会改变你的代码的含义。)