我们正在为最终项目构建处理器。该控制单元是一个状态机,但是它似乎停留在状态中的时间比应有的更长,因此它会重复执行指令。
我们正在使用Vivado 2015.4和Nexys4开发板。
因此,使用一行指令将值存储到加载到指令存储器中的7段中,状态变为:
Fetch =>
Fetch =>
Fetch =>
L_S_D (Load/Store Decode) =>
L_S_E (Load/Store Execute) =>
S_Mem (Store Memory Access) =>
Fetch =>
L_S_D =>
L_S_E =>
S_Mem =>
Fetch =>
L_S_D =>
L_S_E =>
Fetch (forever)
在两个完整的遍历中,显示七个段。第三,它们不完整,没有。
我附加了状态机(相关状态)和程序计数器相关的代码,因为我认为这就是问题所在。
状态机:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity Fred is
Port ( Inst : in STD_LOGIC_vector (31 downto 21);
clk : in std_logic;
rst : in std_logic;
Reg2Loc : out std_logic;
ALUSRC : out std_logic;
MemtoReg : out std_logic;
RegWrite : out std_logic;
Branch : out std_logic;
ALUOp : out std_logic_vector (1 downto 0);
UnconB : out std_logic;
en : out std_logic;
wea : out std_logic;
PCWrite : out std_logic;
REGCEA : out std_logic;
LEDCode : out std_logic_vector (4 downto 0));
end Fred;
architecture Behavioral of Fred is
Type type_fstate is (Fetch, L_S_D, L_S_E, L_Mem, S_Mem,
L_WB, R_I_D, I_E, R_E, I_WB, R_WB, B_E, CBZ_D, B_WB, CBZ_E,
CBZ_WB);
attribute enum_encoding : string;
attribute enum_encoding of type_fstate : type is "one-hot";
signal current_state : type_fstate;
signal next_state : type_fstate;
begin
clockprocess : process (clk, rst, current_state)
begin
if rst = '1' then
next_state <= Fetch;
elsif clk'EVENT and clk = '1' then
next_state <= current_state;
end if;
end process clockprocess;
state_logic: process (next_state)
begin
case next_state is
when Fetch => --00001
if ((Inst = "11111000010")) then --LDUR
current_state <= L_S_D;
elsif ((Inst = "11111000000")) then --STUR
current_state <= L_S_D;
--Additional State Logic Here
else
current_state <= Fetch;
end if;
when L_S_D => --00010
current_state <= L_S_E;
when L_S_E => --00011
if ((Inst = "11111000010")) then
current_state <= L_Mem;
elsif ((Inst = "11111000000")) then
current_state <= S_Mem;
end if;
when S_Mem => --00110
current_state <= Fetch;
--Additional States Here
when others =>
current_state <= Fetch;
end case;
end process state_logic;
output_logic : process (next_state)
begin
case next_state is
when Fetch =>
Reg2Loc <= '0';
ALUSRC <= '0';
MemtoReg <= '0';
RegWrite <= '0';
Branch <= '0';
ALUOp <= "00";
UnconB <= '0';
en <= '0';
wea <= '0';
PCWrite <= '0';
REGCEA <= '1';
LEDCode <= "00001";
when L_S_D =>
Reg2Loc <= '1';
ALUSRC <= '0';
MemtoReg <= '0';
RegWrite <= '0';
Branch <= '0';
ALUOp <= "00";
UnconB <= '0';
en <= '0';
wea <= '0';
PCWrite <= '0';
REGCEA <= '0';
LEDCode <= "00010";
when L_S_E =>
Reg2Loc <= '1';
ALUSRC <= '1';
MemtoReg <= '0';
RegWrite <= '0';
Branch <= '0';
ALUOp <= "00";
UnconB <= '0';
en <= '0';
wea <= '0';
PCWrite <= '1';
REGCEA <= '0';
LEDCode <= "00011";
when S_Mem =>
Reg2Loc <= '1';
ALUSRC <= '1';
MemtoReg <= '0';
RegWrite <= '0';
Branch <= '0';
ALUOp <= "00";
UnconB <= '0';
en <= '1';
wea <= '1';
PCWrite <= '0';
REGCEA <= '0';
LEDCode <= "00110";
--Additional State Outputs Here
when others =>
Reg2Loc <= '0';
ALUSRC <= '0';
MemtoReg <= '0';
RegWrite <= '0';
Branch <= '0';
ALUOp <= "00";
UnconB <= '0';
en <= '0';
wea <= '0';
PCWrite <= '0';
REGCEA <= '0';
LEDCode <= "00000";
end case;
end process output_logic;
end Behavioral;
数据路径:
entity Datapath is
Port (BTNClock : in STD_LOGIC;
clock : in STD_LOGIC;
UncondBranch : in STD_LOGIC;
CondBranch : in STD_LOGIC;
RRtwoSelect : in STD_LOGIC;
RegWriteSelect : in STD_LOGIC;
ALUSource : in STD_LOGIC;
ALUOpCode : in STD_LOGIC_VECTOR(1 downto 0);
WriteSelect : in STD_LOGIC;
MemWrite : in STD_LOGIC;
REGCEA : in STD_LOGIC;
PCWrite : in STD_LOGIC;
seg_select : out STD_LOGIC_vector(6 downto 0);
anode_select : out STD_LOGIC_vector(7 downto 0);
ins_out : out STD_LOGIC_VECTOR(31 downto 0);
RAMSelect : in STD_LOGIC;
ALUEleven : out STD_LOGIC;
REGEleven : out STD_LOGIC;
SwitchReset : in STD_LOGIC);
end Datapath;
architecture Behavioral of Datapath is
signal PC : STD_LOGIC_VECTOR(9 downto 0);
signal instruction : STD_LOGIC_VECTOR(31 downto 0);
signal BranchSelect : STD_LOGIC;
signal ZeroBranch : STD_LOGIC;
signal RRtwo : STD_LOGIC_VECTOR(4 downto 0);
signal RegDataOut1 : STD_LOGIC_VECTOR(63 downto 0);
signal RegDataOut2 : STD_LOGIC_VECTOR(63 downto 0);
signal ALUMuxOut : STD_LOGIC_VECTOR(63 downto 0);
signal SignExtendOut : STD_LOGIC_VECTOR(63 downto 0);
signal BranchExtend : STD_LOGIC_VECTOR(9 downto 0);
signal ALUOut : STD_LOGIC_VECTOR(63 downto 0);
signal ALUZero : STD_LOGIC;
signal MemoryOut : STD_LOGIC_VECTOR(63 downto 0);
signal WriteMuxOut : STD_LOGIC_VECTOR(63 downto 0);
signal Branch : STD_LOGIC_VECTOR(9 downto 0);
signal PCNext : STD_LOGIC_VECTOR(9 downto 0);
signal PCIncrement : STD_LOGIC_VECTOR(9 downto 0);
signal ALUCommand : STD_LOGIC_VECTOR(3 downto 0);
signal InstEn : STD_LOGIC := '1';
signal OnlySeven : STD_LOGIC_VECTOR(0 downto 0);
signal SevSegReset : STD_LOGIC := '0';
begin
OnlySeven(0) <= MemWrite and not ALUOut(11);
BranchSelect <= UncondBranch or ZeroBranch;
ZeroBranch <= CondBranch and ALUZero;
ins_out <= instruction;
ALUEleven <= ALUout(11);
REGEleven <= RegDataOut1(11);
--Program Counter
PCReg : PCounter port map ( clk => BTNClock,
wea => PCWrite,
newaddress => PCNext,
thisaddress => PC);
--Incremental adder
IncAddr : B_adder port map ( a => PC,
x => PCIncrement);
--Branch Adder
BranchAddr : In_adder port map ( a => PC,
b => BranchExtend,
x => Branch);
--Next Instruction Address Mux
NextPCMux : nine_mux port map ( s => BranchSelect,
in1 => PCIncrement,
in2 => Branch,
output => PCNext);
--Additional Datapath Elements Here
end Behavioral;
程序计数器:
entity PCounter is
Port ( clk : in STD_LOGIC; --clock
wea : in STD_LOGIC; --write enable
newaddress : in STD_LOGIC_VECTOR (9 downto 0); --new address coming in
thisaddress : out STD_LOGIC_VECTOR (9 downto 0) --current address to be executed
);
end PCounter;
architecture Behavioral of PCounter is
signal reg: std_logic_vector(9 downto 0); --internal register storage
begin
process(clk) --nothing happens if this register isn't selected
begin
if clk'EVENT and clk = '1' then
thisaddress <= reg; --send out currently saved address
if wea = '1' then
reg <= newaddress; --and set register to next address
end if;
else
reg <= reg; --otherwise, maintain current value
end if;
end process;
end Behavioral;
此加法器仅将PC当前的值加一个:
entity B_adder is
Port ( a : in STD_LOGIC_VECTOR (9 downto 0);
x : out STD_LOGIC_VECTOR (9 downto 0));
end B_adder;
architecture Behavioral of B_adder is
begin
x <= a + 1;
end Behavioral;
这个小复用器将选择下一个地址是来自分支加法器(此处未包括)还是来自上面的增量加法器:
entity nine_mux is
Port ( s : in STD_LOGIC;
in1 : in STD_LOGIC_VECTOR (9 downto 0);
in2 : in STD_LOGIC_VECTOR (9 downto 0);
output : out STD_LOGIC_VECTOR (9 downto 0));
end nine_mux;
architecture Behavioral of nine_mux is
begin
with s select
output <= in1 when '0',
in2 when others;
end Behavioral;
这是控制单元映射到数据路径的方式:
entity WholeThing is
Port ( BTNClock : in STD_LOGIC;
BTNReset : in STD_LOGIC;
SwitchReset : in STD_LOGIC;
clock : in STD_Logic;
LEDs : out STD_LOGIC_VECTOR(4 downto 0);
seg : out STD_LOGIC_vector(6 downto 0);
an : out STD_LOGIC_vector(7 downto 0);
alu11 : out STD_LOGIC;
reg11 : out STD_LOGIC
);
end WholeThing;
architecture Behavioral of WholeThing is
signal instruction : STD_LOGIC_VECTOR(31 downto 0);
signal Reg2Loc : STD_LOGIC;
signal ALUSRC : std_logic;
signal MemtoReg : std_logic;
signal RegWrite : std_logic;
signal Branch : std_logic;
signal ALUOp : std_logic_vector (1 downto 0);
signal UnconB : std_logic;
signal en : std_logic;
signal wea : std_logic;
signal PCWrite : std_logic;
signal REGCEA : std_logic;
signal SwRst : STD_LOGIC;
begin
--SwitchReset <= SwRst;
--Control Unit
CU : Fred port map ( Inst => instruction(31 downto 21),
clk => BTNClock,
rst => BTNReset,
Reg2Loc => Reg2Loc,
ALUSRC => ALUSRC,
MemtoReg => MemtoReg,
RegWrite =>RegWrite,
Branch => Branch,
ALUOp => ALUOp,
UnconB => UnconB,
en => en,
wea => wea,
PCWrite => PCWrite,
REGCEA => REGCEA,
LEDCode => LEDs);
--Datapath
DP : Datapath port map (BTNClock => BTNClock,
clock => clock,
UncondBranch => UnconB,
CondBranch => Branch,
RRtwoSelect => Reg2Loc,
RegWriteSelect => RegWrite,
ALUSource => ALUSRC,
ALUOpCode => ALUOp,
WriteSelect => MemtoReg,
MemWrite => wea,
REGCEA => REGCEA,
PCWrite => PCWrite,
seg_select => seg,
anode_select => an,
ins_out => instruction,
RAMSelect => en,
ALUEleven => alu11,
REGEleven => reg11,
SwitchReset => SwitchReset
);
end Behavioral;
答案 0 :(得分:1)
您的第二个过程应实现默认分配,以节省大量不必要的else分支,在这些分支中您定义了FSM图的自镶边。因为您错过了,所以FSM为信号current_state
创建了附加的锁存器!检查综合报告中是否存在闩锁警告,您可能会发现其中的多个警告。
您混合了current_state
和next_state
。信号的含义不
反映您的代码!您的case语句需要打开current_state
。
不要使用3进程模式来描述FSM。这是一场噩梦 可读性和维护性!一个人可以阅读并验证此FSM表单的行为。
您使用错误的方式使用了enum_encoding属性:
fsm_encoding
应用于状态信号fsm_encoding
的值为user
应用于状态信号,并将enum_encoding
的二进制值以空格分隔的列表应用于您的状态类型。请勿使用异步重置。同步的时钟进程在灵敏度列表中只有一个信号!
联合流程需要在该列表中列出所有读取的信号!
您不应使用clk'EVENT and clk = '1'
。请改用rising_edge(clk)
。
如果您多次打开同一信号,请使用case语句,但不要使用if-elsif构造!
您的眼睛以及您的LED可能不够快,无法看到和显示LEDCode
。
更正的代码:
architecture Behavioral of Fred is
attribute fsm_encoding : string;
type type_fstate is (
Fetch, L_S_D, L_S_E, L_Mem, S_Mem,
L_WB, R_I_D, I_E, R_E, I_WB, R_WB, B_E, CBZ_D, B_WB, CBZ_E,
CBZ_WB);
signal current_state : type_fstate := Fetch;
signal next_state : type_fstate;
attribute fsm_encoding of current_state : signal is "one-hot";
begin
clockprocess : process(clk)
begin
if rising_edge(clk) then
if rst = '1' then
current_state <= Fetch;
else
current_state <= next_state;
end if;
end if;
end process;
state_logic: process (current_state, Inst)
begin
next_state <= current_state;
Reg2Loc <= '0';
ALUSRC <= '0';
MemtoReg <= '0';
RegWrite <= '0';
Branch <= '0';
ALUOp <= "00";
UnconB <= '0';
en <= '0';
wea <= '0';
PCWrite <= '0';
REGCEA <= '0';
LEDCode <= "00000";
case current_state is
when Fetch => --00001
REGCEA <= '1';
LEDCode <= "00001";
case Inst is
when "11111000010" => --LDUR
next_state <= L_S_D;
when "11111000000" => --STUR
next_state <= L_S_D;
--Additional State Logic Here
when others =>
next_state <= Fetch;
end case;
when L_S_D => --00010
Reg2Loc <= '1';
LEDCode <= "00010";
next_state <= L_S_E;
when L_S_E => --00011
Reg2Loc <= '1';
ALUSRC <= '1';
PCWrite <= '1';
LEDCode <= "00011";
case Inst is
when "11111000010" =>
next_state <= L_Mem;
when "11111000000" =>
next_state <= S_Mem;
when others =>
-- ???
end case;
when S_Mem => --00110
Reg2Loc <= '1';
ALUSRC <= '1';
en <= '1';
wea <= '1';
LEDCode <= "00110";
next_state <= Fetch;
--Additional States Here
when others =>
next_state <= Fetch;
end case;
end process;
end architecture;
请不要在VHDL中分配类似reg <= reg
的内容!
您正在对类型std_logic_vector
使用算术。该操作是:
synopsys.std_logic_unsigned
之类的非IEEE程序包,完全不应该使用。如果需要算术运算,请使用软件包ieee.numeric_std
和类型signed
/ unsigned
。您的程序计数器(PC)不计数(还?)。根据单一责任原则,您的PC应该能够:
您的PC为输出thisaddress
分配了一个延迟周期。通常,这会破坏任何CPU功能...
当您要在FPGA器件上实现设计时,请确保使用适当的初始化值初始化所有转换为存储器(例如寄存器)的信号。
改进的代码:
architecture Behavioral of PCounter is
signal reg: unsigned(9 downto 0) := (others => '0');
begin
process(clk)
begin
if rising_edge(clk) then
if wea = '1' then
reg <= unsigned(newaddress);
end if;
end if;
end process;
thisaddress <= reg;
end architecture;
B_adder
在消耗9行代码的实体中实现一行代码明智吗?
而且,您的代码描述的是增量器,而不是加法器。
没有用with ... select
语句描述多路复用器。这将创建一个优先级逻辑,例如一系列if-elseif分支。
output <= in1 when (s = '0') else in2;
由于现在这是一个不受大小限制的单线,所以请拧紧nine_mux实体。