项目地址:FPGA、VHDL 基于RISC-V格式的16位位缩模型机设计
-
设计目的
实现基于RISC-V格式的16位MCU设计,参考RISC-V的基本格式,进行位数缩减。实现RISC-V中寄存器加法add,立即数加法addi,半字加载lh,半字存储sh,不等条件跳转bne,相等条件跳转beq,无条件跳转链接jal。实现立即寻址、寄存器寻址、基址寻址、相对寻址。通过测试程序测试内存读取、加法运算、分支跳转的实现。
-
设计过程
首先确定模型机位数,确定指令格式与寻址方式。指令格式由RISC-V基本格式做位数缩减得到。寻址方式有立即数寻址、寄存器寻址、基址寻址、相对寻址。其次确定指令集与测试程序。然后画出微程序流程图,得到控制状态机。之后完善各部分器件原理图或代码,最后通过测试程序测试模型机功能。
模型机位数选定为16位,采用单总线结构。模型机设计包括:16位4片寄存器堆REG、单端口运算器ALU、读取存储器RAM、程序计数器PC、控制器CTL、时序产生单元STEP。
2.1指令集设计
指令格式:
基于RISC-V基本格式,位数缩减至16位。
表 1指令格式
指令格式类型 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | 指令类型 |
R型 | funct4 | rs2 | rs1 | funct3 | rd | opcode | 运算指令 | ||||||||||
I型 | imm[5:0] | rs1 | funct3 | rd | opcode | 装数/立 即数运算 | |||||||||||
S型 | imm[5:2] | rs2 | rs1 | funct3 | imm[1:0] | opcode | 存数指令 | ||||||||||
B型 | imm[5:2] | rs2 | rs1 | funct3 | imm[1:0] | opcode | 条件分 支指令 | ||||||||||
J型 | imm[10:0] | rd | opcode | 无条件 跳转指令 |
指令集:
ADD
助记符:add rd,rs1,rs2
功能:R[rd] = R[rs1] + R[rs2],把寄存器 R[rs2] 加寄存器 R[rs1],结果写入 R[rd]。
指令:
funct4 | rs2 | rs1 | funct3 | rd | opcode | ||||||||||
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
ADDI
助记符:addi rd, rs1, immediate
功能:R[rd] = R[rs1] + sext(immediate),把符号位扩展的立即数加到寄存器 R[rs1]上,结果写入 R[rd]。
指令:
imm[5:0] | rs1 | funct3 | rd | opcode | |||||||||||
0 | 0 | 1 | 0 | 0 | 1 |
LH
助记符:lh rd,offset(rs1)
功能:R[rd] = sext(M[R[rs1] + sext(offset)][15:0]),半字加载,从地址 R[rs1] + sign-extend(offset)读取16位数据,写入R[rd]
指令:
imm[5:0] | rs1 | funct3 | rd | opcode | |||||||||||
0 | 0 | 0 | 0 | 0 | 1 |
SH
助记符:sh rs2, offset(rs1)
功能:M[R[rs1] + sext(offset) = R[rs2][15: 0],将 R[rs2]的16位数据存入内存地址 R[rs1]+sign-extend(offset)。
指令:
imm[5:2] | rs2 | rs1 | funct3 | imm[1:0] | opcode | ||||||||||
0 | 0 | 0 | 0 | 1 | 0 |
BNE
助记符:bne rs1, rs2, offset
功能:if (rs1 ≠ rs2) pc += sext(offset),若寄存器 R[rs1]和寄存器 R[rs2]的值不相等,把 pc 的值设为当前值加上符号位扩展的偏移 offset。
指令:
imm[5:2] | rs2 | rs1 | funct3 | imm[1:0] | opcode | ||||||||||
0 | 0 | 0 | 0 | 1 | 1 |
BEQ
助记符:beq rs1, rs2, offset
功能:if (rs1 = rs2) pc += sext(offset),若寄存器 R[rs1]和寄存器 R[rs2]的值相等,把 pc 的值设为当前值加上符号位扩展的偏移 offset。
指令:
imm[5:2] | rs2 | rs1 | funct3 | imm[1:0] | opcode | ||||||||||
0 | 0 | 1 | 0 | 1 | 1 |
JAL
助记符:jal rd, offset
功能:R[rd] = pc+1; pc += sext(offset),把下一条指令的地址(pc+1)保存到目的寄存器,然后把 pc 设置为当前值加上符号位扩展的offset。
指令:
imm[10:0] | rd | opcode | |||||||||||||
1 | 0 | 0 |
2.2 模块设计
2.2.1寄存器堆
16位D触发器dff1代码:
library ieee;
use ieee.std_logic_1164.all;
entity dff1 is
port (
clk : in std_logic;
d : in STD_LOGIC_VECTOR(15 downto 0);
q : out STD_LOGIC_VECTOR(15 downto 0)
);
end entity dff1;
architecture bhv of dff1 is
signal q1 : std_logic_vector(15 downto 0);
begin
process (clk,q1)
begin
if clk'EVENT AND clk = '1'
then
q1 <= d;
end if;
end process;
q <= q1;
end architecture bhv;
dff1仿真:
clk上升沿时,将输入端d[15..0]存入其中。
寄存器堆设计图:
由4个D触发器dff1组成,4个LD_REG作写选通,2位SEL[1..0]和REG_B作写总线控制。
寄存器堆REG仿真:
先读R0,输出0000;同时写R1=FFFF。
然后读R1,输出FFFF。
2.2.2 运算器模块
ALU181代码:
S=1001,进行加法运算;S=0110,进行减法运算;S=0000,不做操作。FZ为零标志。
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY ALU181 IS
PORT (
S : IN STD_LOGIC_VECTOR(3 DOWNTO 0 );
A,B : IN STD_LOGIC_VECTOR(15 DOWNTO 0);
F : OUT STD_LOGIC_VECTOR(15 DOWNTO 0);
COUT : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
M,CN : IN STD_LOGIC;
CO,FZ : OUT STD_LOGIC
);
END ALU181;
ARCHITECTURE behav OF ALU181 IS
SIGNAL A9,B9,F9 : STD_LOGIC_VECTOR(16 DOWNTO 0);
BEGIN
A9 <= '0' & A ; B9 <= '0' & B ;
PROCESS(M,CN,A9,B9)
BEGIN
CASE S IS
WHEN "0000" =>NULL;
WHEN "0001" =>IF M='0' THEN F9<=(A9 OR B9)+CN; ELSE F9<=NOT(A9 OR B9); END IF;
WHEN "0010" =>IF M='0' THEN F9<=(A9 OR (NOT B9))+CN; ELSE F9<=(NOT A9) AND B9; END IF;
WHEN "0011" =>IF M='0' THEN F9<= "00000000000000000"-CN; ELSE F9<="00000000000000000"; END IF;
WHEN "0100" =>IF M='0' THEN F9<=A9+(A9 AND NOT B9)+CN; ELSE F9<=NOT (A9 AND B9); END IF;
WHEN "0101" =>IF M='0' THEN F9<=(A9 OR B9)+(A9 AND NOT B9)+CN; ELSE F9<=NOT B9; END IF;
WHEN "0110" =>IF M='0' THEN F9<=A9 -B9 - CN; ELSE F9<=A9 XOR B9; END IF;
WHEN "0111" =>IF M='0' THEN F9<=(A9 AND (NOT B9))-CN; ELSE F9<=A9 AND (NOT B9); END IF;
WHEN "1000" =>IF M='0' THEN F9<=A9 + (A9 AND B9)+CN; ELSE F9<=(NOT A9) OR B9; END IF;
WHEN "1001" =>IF M='0' THEN F9<=A9 + B9 + CN; ELSE F9<=NOT(A9 XOR B9); END IF;
WHEN "1010" =>IF M='0' THEN F9<=(A9 OR (NOT B9))+(A9 AND B9)+CN; ELSE F9<=B9; END IF;
WHEN "1011" =>IF M='0' THEN F9<=(A9 AND B9)- CN; ELSE F9<=A9 AND B9; END IF;
WHEN "1100" =>IF M='0' THEN F9<=A9 + A9 + CN; ELSE F9<= "00000000000000001"; END IF;
WHEN "1101" =>IF M='0' THEN F9<=(A9 OR B9)+A9 + CN; ELSE F9<=A9 OR (NOT B9); END IF;
WHEN "1110" =>IF M='0' THEN F9<=(A9 OR(NOT B9))+A9+CN; ELSE F9<=A9 OR B9; END IF;
WHEN "1111" =>IF M='0' THEN F9<=A9-CN; ELSE F9<=A9; END IF;
WHEN OTHERS =>F9<= "00000000000000000" ;
END CASE;
IF (F9 = "00000000000000000") THEN FZ <= '1'; ELSE FZ <= '0'; END IF;
END PROCESS;
F<= F9(15 DOWNTO 0); CO <= F9(16);
COUT <= "0000" WHEN F9(16) = '0' ELSE "0001" ;
END behav;
ALU设计图:
D[15..0]:总线输入;
2个LD_DR:数据寄存器DR写选通;
S[3..0]:运算选择;
M:模式选择;
CN:进位输入;
ALU_B:结果写总线控制。
F[15..0]:结果输出;
COUT[3..0]:进位输出;
CO:进位标志;
FZ:零标志。
ALU仿真:
依次DR0存入0004、DR1存入0004,S=0110做减法。结果为0000,零标志FZ=1
2.2.3 存储器模块
RAM设计图:
AR_CLK:地址寄存器AR时序输入
RAM_CLK:读取存储器RAM时序输入
LD_AR:AR写选通
W/R:RAM读写控制,低电平读,高电平写
RAM_B:存储模块写总线控制,高电平输出到总线
RAM绑定初始数据mif:
将测试程序二进制码存为mif文件,绑定到lpm_ram_dq中。
RAM仿真:
初始AR=0000,在第一个RAM_CLK上升沿后,读出[0000H]=2821H;
之后写入AR=0001H,可读出[0001H]=0929H;
再写入AR=0010H,读出[0010H]=0000H;
置W/R=1,数据FFFFH存入[0010H],之后读出[0010H]=FFFFH。
2.2.4 其他模块
TIMER(STEP)设计图:
CLK:时钟输入
RST:高电平重置
TIMER(STEP)仿真:
CLK分出时序T1、T2、T3、T4。
RST高电平时重置。
PC设计图:
LD_PC:PC置数
INC_PC:PC+1
ACLR:异步清零
PC_B:PC写总线控制
PC仿真:
INC_PC置1时,PC+1;
ACLR置1时,PC清零;
LD_PC=1且INC_PC=1时,执行置数操作,使PC=D[15..0]。
2.2.5 控制器模块
采用状态机控制:
流程图:
状态控制信号表:
序号 | 作用 | REG | ALU | RAM | PC | IR | IMM/OFFSET | |||||||||||||||||||
LD_REG3 | LD_REG2 | LD_REG1 | LD_REG0 | SEL1 | SEL0 | REG_B | LD_DR1 | LD_DR0 | S3 | S2 | S1 | S0 | CN | M | ALU_B | LD_AR | W/R | RAM_B | LD_PC | INC_PC | ACLR | PC_B | LD_IR | IMM_B | ||
位数 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | |
0 | PC->AR | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 |
1 | RAM->IR | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 1 | 0 |
2 | rs1->DR0 | 0 | 0 | 0 | 0 | rs1 | rs1 | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
3 | rs2->DR1 | 0 | 0 | 0 | 0 | rs2 | rs2 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
4 | DR0+DR1->rd,PC+1 | rd | rd | rd | rd | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 |
5 | imm->DR1/offset->DR1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
6 | DR0+DR1->AR | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 0 | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
7 | RAM->rd,PC+1 | rd | rd | rd | rd | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 0 | 0 | 0 | 0 |
8 | rs2->RAM,PC+1 | 0 | 0 | 0 | 0 | rs2 | rs2 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 0 | 0 | 0 | 0 |
9 | DR0-DR1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
10 | PC->DR0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 |
11 | DR0+DR1->PC | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 0 | 0 | 1 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 0 | 0 |
12 | PC->DR0,PC+1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 0 | 0 |
13 | PC->rd | rd | rd | rd | rd | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 |
14 | PC+1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 |
状态转移图:
状态转移表:
Source State | Destination State | Condition |
s0 | s1 | |
s1 | s12 | (!OP[0]).(!OP[1]).(OP[2]) |
s1 | s2 | (!OP[0]).(!OP[1]).(!OP[2]) + (!OP[0]).(OP[1]) + (OP[0]) |
s2 | s5 | (!OP[0]).(!OP[1]).(OP[2]) + (!OP[0]).(OP[1]) + (OP[0]).(!OP[1]) + (OP[0]).(OP[1]).(OP[2]) |
s2 | s3 | (!OP[0]).(!OP[1]).(!OP[2]) + (OP[0]).(OP[1]).(!OP[2]) |
s3 | s9 | (!OP[0]).(!OP[1]).(OP[2]) + (!OP[0]).(OP[1]) + (OP[0]) |
s3 | s4 | (!OP[0]).(!OP[1]).(!OP[2]) |
s4 | s0 | |
s5 | s4 | (OP[0]).(!OP[1]).(!OP[2]).(FUNCT3[0]).(!FUNCT3[1]).(!FUNCT3[2]) |
s5 | s6 | (!OP[0]).(OP[1]).(!OP[2]) + (OP[0]).(!OP[1]).(!OP[2]).(!FUNCT3[0]).(!FUNCT3[1]).(!FUNCT3[2]) |
s5 | s11 | (!OP[0]).(!OP[1]) + (!OP[0]).(OP[1]).(OP[2]) + (OP[0]).(!OP[1]).(!OP[2]).(!FUNCT3[1]).(FUNCT3[2]) + (OP[0]).(!OP[1]).(!OP[2]).(FUNCT3[1]) + (OP[0]).(!OP[1]).(OP[2]) + (OP[0]).(OP[1]) |
s6 | s7 | (OP[0]).(!OP[1]).(!OP[2]) |
s6 | s8 | (!OP[0]) + (OP[0]).(!OP[1]).(OP[2]) + (OP[0]).(OP[1]) |
s7 | s0 | |
s8 | s0 | |
s9 | s14 | (!FZ).(!FUNCT3[0]).(!FUNCT3[1]).(FUNCT3[2]) + (!FZ).(!FUNCT3[0]).(FUNCT3[1]) + (!FZ).(FUNCT3[0]) + (FZ).(!FUNCT3[0]).(!FUNCT3[1]).(!FUNCT3[2]) |
s9 | s10 | (!FZ).(!FUNCT3[0]).(!FUNCT3[1]).(!FUNCT3[2]) + (FZ).(!FUNCT3[0]).(!FUNCT3[1]).(FUNCT3[2]) + (FZ).(!FUNCT3[0]).(FUNCT3[1]) + (FZ).(FUNCT3[0]) |
s10 | s5 | |
s11 | s0 | |
s12 | s13 | |
s13 | s5 | |
s14 | s0 |
控制器模块ctl包括:指令寄存器IR、指令分析器ia、状态机sm
指令分析器ia代码:
根据输入的指令,分析出操作码、源寄存器、目的寄存器、功能选择、扩展立即数。
I:指令输入
RD:目的寄存器
RS1,RS2:源寄存器
OP:操作码
FUNCT3:功能选择
IMM:符号位扩展后的16位立即数
IMM_B:立即数写总线控制
decode24:24译码器函数
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY ia IS
PORT (
CLK: IN STD_LOGIC; --时钟信号
I: IN STD_LOGIC_VECTOR(15 DOWNTO 0); --16位输入信号,表示指令
RD: OUT STD_LOGIC_VECTOR(3 DOWNTO 0); --4位输出信号,表示所选寄存器3210
RS1, RS2: OUT STD_LOGIC_VECTOR(1 DOWNTO 0); --2位输出信号
OP: OUT STD_LOGIC_VECTOR(2 DOWNTO 0); --3位输出信号,表示操作码
FUNCT3: OUT STD_LOGIC_VECTOR(2 DOWNTO 0); --3位输出信号,表示功能选择
IMM: OUT STD_LOGIC_VECTOR(15 DOWNTO 0) --16位输出信号,表示立即数
);
END ia;
ARCHITECTURE behav OF ia IS
FUNCTION decode24(x : IN STD_LOGIC_VECTOR(1 DOWNTO 0)) RETURN STD_LOGIC_VECTOR IS --返回值不写长度
BEGIN
CASE x IS
WHEN "00" => RETURN "0001";
WHEN "01" => RETURN "0010";
WHEN "10" => RETURN "0100";
WHEN "11" => RETURN "1000";
END CASE;
END FUNCTION decode24;
SIGNAL opcode : STD_LOGIC_VECTOR(2 DOWNTO 0);
BEGIN
opcode <= I(2 DOWNTO 0);
PROCESS(CLK, I, opcode)
BEGIN
IF CLK = '1'
THEN
CASE opcode IS
WHEN "000" => --R型指令,只有ADD
RD <= decode24(I(4 DOWNTO 3));
RS1 <= I(9 DOWNTO 8);
RS2 <= I(11 DOWNTO 10);
WHEN "001" => --I型指令,只有ADDI,LH
RD <= decode24(I(4 DOWNTO 3));
FUNCT3 <= I(7 DOWNTO 5);
RS1 <= I(9 DOWNTO 8);
IF I(15) = '0' THEN IMM <= "0000000000" & I(15 DOWNTO 10); ELSE IMM <= "1111111111" & I(15 DOWNTO 10); END IF;
WHEN "010" => --S型指令,只有SH
RS1 <= I(9 DOWNTO 8);
RS2 <= I(11 DOWNTO 10);
IF I(15) = '0' THEN IMM <= "0000000000" & I(15 DOWNTO 12) & I(4 DOWNTO 3); ELSE IMM <= "1111111111" & I(15 DOWNTO 12) & I(4 DOWNTO 3); END IF;
WHEN "011" => --B型指令,只有BNE,BEQ
FUNCT3 <= I(7 DOWNTO 5);
RS1 <= I(9 DOWNTO 8);
RS2 <= I(11 DOWNTO 10);
IF I(15) = '0' THEN IMM <= "0000000000" & I(15 DOWNTO 12) & I(4 DOWNTO 3); ELSE IMM <= "1111111111" & I(15 DOWNTO 12) & I(4 DOWNTO 3); END IF;
WHEN "100" => --J型指令,只有JAL
RD <= decode24(I(4 DOWNTO 3));
IF I(15) = '0' THEN IMM <= "00000" & I(15 DOWNTO 5); ELSE IMM <= "11111" & I(15 DOWNTO 5); END IF;
WHEN OTHERS => NULL;
END CASE;
END IF;
OP <= opcode;
END PROCESS;
END behav;
状态机sm代码:
进程1中根据输入的OP、FUNCT3、FZ以及当前状态,确定新的状态。
进程2中根据当前状态和寄存器编码RD、RS1、RS2输出相应的控制信号C[24..0]。
1.-- Quartus Prime VHDL Template
2.-- Four-State Moore State Machine
3.-- 211540882
4.-- A Moore machine's CTLs are dependent only on the current state.
5.-- The CTL is written only when the state changes. (State
6.-- transitions are synchronous.)
7.
8.library ieee;
9.use ieee.std_logic_1164.all;
10.use ieee.std_logic_unsigned.all;
11.
12.entity sm is
13. port(
14. CLK : in std_logic;
15. RD : in std_logic_vector(3 downto 0);
16. OP, FUNCT3 : in std_logic_vector(2 downto 0);
17. RS1, RS2 : in std_logic_vector(1 downto 0);
18. FZ : in std_logic;
19. RST : in std_logic;
20. CTL : out std_logic_vector(24 downto 0));
21.end entity;
22.
23.architecture rtl of sm is
24.
25. -- Build an enumerated type for the state machine
26. type state_type is (s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14);
27.
28. -- Register to hold the current state
29. signal state : state_type;
30.
31.begin
32. -- Logic to advance to the next state
33. process (CLK, RST, OP, FUNCT3, FZ)
34. begin
35. if RST = '1' then
36. state <= s0;
37. elsif (rising_edge(CLK)) then
38. case state is
39. when s0=>
40. state <= s1;
41. when s1=>
42. if OP = "100" then
43. state <= s12;
44. else
45. state <= s2;
46. end if;
47. when s2=>
48. if OP = "000" or OP = "011" then
49. state <= s3;
50. else
51. state <= s5;
52. end if;
53. when s3 =>
54. if OP = "000" then
55. state <= s4;
56. else
57. state <= s9;
58. end if;
59. when s4 =>
60. state <= s0;
61. when s5 =>
62. if OP = "001" and FUNCT3 = "001" then
63. state <= s4;
64. elsif (OP = "001" and FUNCT3 = "000") or OP = "010" then
65. state <= s6;
66. else
67. state <= s11;
68. end if;
69. when s6 =>
70. if OP = "001" then
71. state <= s7;
72. else
73. state <= s8;
74. end if;
75. when s7 =>
76. state <= s0;
77. when s8 =>
78. state <= s0;
79. when s9 =>
80. if FUNCT3 = "000" then
81. if FZ = '0' then
82. state <= s10;
83. else
84. state <= s14;
85. end if;
86. else
87. if FZ = '1' then
88. state <= s10;
89. else
90. state <= s14;
91. end if;
92. end if;
93. when s10 =>
94. state <= s5;
95. when s11 =>
96. state <= s0;
97. when s12 =>
98. state <= s13;
99. when s13 =>
100. state <= s5;
101. when s14 =>
102. state <= s0;
103. end case;
104. end if;
105. end process;
106.
107. -- CTL depends solely on the current state
108. process (state, RS1, RS2, RD)
109. begin
110. case state is
111. when s0 =>
112. CTL <= "0000000000000000100000100";
113. when s1 =>
114. CTL <= "0000000000000000001000010";
115. when s2 =>
116. CTL <= "0000" & RS1 & "1010000000000000000";
117. when s3 =>
118. CTL <= "0000" & RS2 & "1100000000000000000";
119. when s4 =>
120. CTL <= RD & "000001001001000010000";
121. when s5 =>
122. CTL <= "0000000100000000000000001";
123. when s6 =>
124. CTL <= "0000000001001001100000000";
125. when s7 =>
126. CTL <= RD & "000000000000001010000";
127. when s8 =>
128. CTL <= "0000" & RS2 & "1000000000010010000";
129. when s9 =>
130. CTL <= "0000000000110000000000000";
131. when s10 =>
132. CTL <= "0000000010000000000000100";
133. when s11 =>
134. CTL <= "0000000001001001000110000";
135. when s12 =>
136. CTL <= "0000000010000000000010100";
137. when s13 =>
138. CTL <= RD & "000000000000000000100";
139. when s14 =>
140. CTL <= "0000000000000000000010000";
141. end case;
142. end process;
143.end rtl;
控制器ctl设计图:
控制器ctl仿真:
测试指令:addi r0, r0, 10;16进制为2821H
首先进入状态S0,输出控制位0000104H,控制PC值写入AR;
然后到状态S1,输出控制位0000042H,控制读指令2821H到IR;
然后到状态S2,输出控制位0050000H,控制rs1的值写入DR0;
然后到状态S5,输出控制位0020001H,控制立即数扩展后写入DR1;
然后到状态S4,输出控制位0209210H,控制结果写入rd。
2.3整机调试
2.3.1测试程序设计
地址(16进制) | 内容(16进制) | 助记符 | 说明 |
0000 | 2821 | addi r0, r0, 10; | r0 += 10; |
0001 | 0929 | addi r1, r1, 2; | r1 += 2; |
0002 | F41B | bne r0, r1, -1; | if(r0 != r1) pc -= 1; |
0003 | 540A | sh r1, 21(r0); | [r0 + 21] = r1; |
0004 | 5511 | lh r2, 21(r1); | r2 = [r1 + 21]; |
0005 | 0900 | add r0, r1, r2; | r0 = r1 + r2; |
0006 | 2929 | addi r1, r1, 10; | r1 += 10; |
0007 | F43B | beq r0, r1, -1; | if(r0 == r1) pc -= 1; |
0008 | FF04 | jal r0, -8; | r0 = pc +1; pc -= 8; |
2.3.2 仿真结果
- 第0条指令:addi r0, r0, 10,R0 += 10,最后R0 = 10。
-
序号
地址A
指令
状态机
控制位C
总线BUS
结果
0
0000
2821
S0
000 0104
0000
写AR:0000
S1
000 0042
2821
取指令,写入IR:2821
S2
005 0000
0000
R0->DR0
S5
002 0001
000A
10->DR1
S4
020 9210
000A
做加法,结果写回R0
后面的仿真结果省略………………
标签:FPGA,VHDL,16,rd,PC,FUNCT3,rs1,rs2,OP From: https://blog.csdn.net/m0_69150145/article/details/143216435