课程设计内容
设计实现一个字长8位的CPU,所设计的系统能调试通过,通过运行自行编写的程序进行仿真测试,通过检查程序结果的正确性来判断所设计计算机系统的正确性。
课程设计要求
1、提前熟悉CPU的各个组成部分,以及Verilog语言和Quartus II软件的使用方法。
2、可使用如图1所示的数据通路设计CPU。
请注意:每一届都会有微小的变动,如果需要高分请认真学习并理解原理后完成课设。
请特别注意:本代码为线上授课期间课设任务,答辩仅需要在软件上模拟波形即可,目前学校的答辩需要在电路板上实体操作,并非软件模拟。
本代码未实现现代时序设计控制器。当时sheep了,没力气做了。
给分情况:ljh>zhy>>>drf,尽可能早答辩,给分会高。
说明:AR、PC是16位寄存器,直接连接到16位总线,其余8位寄存器连接到16位总线的低8位。
可以用传统时序和现代时序设计控制器,如果用现代时序设计控制器得分高。
3、确定指令格式,按照以下要求,至少完成以下(1)-(4)必做指令:
(1)空指令NOP ;空操作
(2)算术逻辑运算类指令:(实现8条指令,CLR必做)
- 双操作数算术运算指令:ADD、SUB ;R0和R1运算,结果送R0
- 双操作数逻辑运算指令:AND、OR、XOR ;R0和R1运算,结果送R0
- 单操作数指令:INC、DEC、NOT ;对R0运算,结果送R0
- 清零指令(无操作数):CLR ;R0<—0
(3)移位指令:(实现1条)
- SHR、SHL ;对R0运算,结果送R0
(4)寄存器-寄存器传送指令
- MVR ;R1<—R0
(5)无条件跳转指令:JMP A(选做) ;A为跳转到的地址
(6)条件跳转指令:(选做)
- JPZ A ;z=1时跳转,A为跳转到的地址
- JPNZ A ;z=0时跳转,A为跳转到的地址
注意需要加零标志寄存器Z
(7)寄存器-存储器数据传送(选做)
- LAD A ;R0<—M[A]
- STO A ;M[A] <—R0
注意:以上必做指令都是单字指令,操作数都是R0和R1,除了MVR指令外,目的操作数都是R0,因此不需要在指令中指明操作数,只提供操作码(8位)即可。例如ADD指令就是做R0+R1—>R0。以上选做指令都是三字指令,操作码8位地址码16位。
4、确定各指令的执行流程图和所需要的控制信号。
5、设计出实现指令功能的硬布线控制器,明确运算器的功能。
6、能运行由自己所设计的指令系统构成的一段程序,程序执行功能正确。
7、对程序进行仿真,能够理解仿真波形图。
8、撰写课程设计报告。
课设代码(仅供参考,请不要抄袭,独立完成)
alu.v
/*算术逻辑单元*/
module alu(alus,x, bus, dout);
input [3:0]alus;
input [7:0]bus,x;
output reg[7:0]dout;
always@(alus or x or bus)
case(alus)
4'b0000: dout = 8'b00000000;//CLR
4'b0001: dout = x + bus;//ADD
4'b0010: dout = x - bus;//SUB
4'b0011: dout = x & bus;//AND
4'b0100: dout = x | bus;//OR
4'b0101: dout = (~x&bus)|(x&~bus);//XOR
4'b0110: dout = x + 8'b00000001;//INC
4'b0111: dout = x - 8'b00000001;//DEC
4'b1000: dout = ~x;//NOT
4'b1001: dout = x * 8'b00000010;//SHL
4'b1010: dout = x / 8'b00000010;//SHR
4'b1011: dout = bus + 8'b00000000;//LAD
endcase
endmodule
ar.v
/*地址寄存器,输出要执行的下一指令地址*/
module ar(din, clk, rst,arload, arinc, dout);
input[15:0] din;
input clk,rst,arload, arinc;
output [15:0]dout;
reg [15:0]dout;
always@(posedge clk or negedge rst)
if(!rst)
dout<=0;
else
begin
if(arload)
dout<=din;
else if(arinc)
dout<=dout+1;
end
endmodule
clk_div.v
/*分频程序*/
//`timescale 1ns / 1ps
//`include"headfile.v"
module clk_div(clk,reset,symbol,div_clk);
input clk;
input reset;
input [31:0] symbol;
output reg div_clk;
reg [31:0] count;
always @(posedge clk)
begin
if (!reset)
begin
div_clk <= 1;
count <= 0;
end
else
begin
if(count == symbol)
begin
div_clk <= ~div_clk;
count <= 0;
end
else
count <= count + 1'b1;
end
end
endmodule
control.v
/*组合逻辑控制单元,根据时钟生成为控制信号和内部信号*/
/*
输入:
din:指令,8位,来自IR;
clk:时钟信号,1位,上升沿有效;
rst:复位信号,1位,与cpustate共同组成reset信号;
cpustate:当前CPU的状态(IN,CHECK,RUN),2位;
z:零标志,1位,零标志寄存器的输出,如果指令中涉及到z,可加上,否则可去掉;
输出:
clr:清零控制信号
自行设计的各个控制信号
*/
//省略号中是自行设计的控制信号,需要自行补充,没用到z的话去掉z
module control(din,clk,rst,z,cpustate,read,write,membus,
busmem,arload,arinc,pcload,pcinc,pcbus,
drload,drbus,trload,trbus,irload,r1load,r1bus,
alus,zload,r0load,r0bus,drhbus,drlbus,xload,clr);
input [7:0]din;
input clk;
input rst,z;
input [1:0] cpustate;
//输出端口说明
output irload,r1load,r1bus,zload,xload,r0load,r0bus,read,write,membus,
busmem,arload,arinc,pcload,pcinc,pcbus,drload,drbus,trload,
trbus,drhbus,drlbus,clr;
output [3:0]alus;
//parameter's define
wire reset;
//在下方加上自行定义的状态 用assign赋值的都为wire
wire fetch1,fetch2,fetch3,nop1;
wire mvr1,add1,sub1,and1,or1,xor1,inc1,dec1,clr1,not1,shl1,shr1;
wire add2,sub2,and2,or2,xor2;
wire lad1,lad2,lad3,lad4,lad5;
wire sto1,sto2,sto3,sto4,sto5;
wire jmp1,jmp2,jmp3;
wire jpz1,jpz2,jpz3;//z=1
wire jpnz1,jpnz2,jpnz3;//z=0
reg inop,iadd,isub,iand,ior,ixor,iinc,idec,iclr,inot,ishl,ishr,imvr,ilad,isto,ijpz,ijmp,ijpnz; //在always中赋值
//时钟节拍,8个为一个指令周期,t0-t2分别对应fetch1-fetch3,t3-t7分别对应各指令的执行周期,当然不是所有指令都需要5个节拍的。例如add指令只需要一个t3
reg t0,t1,t2,t3,t4,t5,t6,t7;
// signals for the counter, 内部信号:clr清零,inc自增
wire clr;
wire inc;
assign reset = rst&(cpustate == 2'b11);
//clr信号是每条指令执行完毕后必做的清零,下面赋值语句要修改,需要“或”各指令的最后一个周期
//assign clr=nop1||mvr1||add1||sub1||and1||or1||xor1||inc1||clr1||not1||lad5||sto5||jpz3||jpz3||jpnz3;
assign clr=nop1||mvr1||add2||sub2||and2||or2||xor2||inc1||dec1||shl1||shr1||clr1||not1||lad5||sto5||jmp3||jpz3||jpnz3;
assign inc=~clr;
//generate the control signal using state information
//取公共指令过程
// 用assign连续赋值必须为wire型
assign fetch1=t0;
assign fetch2=t1;
assign fetch3=t2;
//空
assign nop1 = inop&&t3;//inop表示nop指令,nop1是nop指令的执行周期的第一个状态也是最后一个状态,因为只需要1个节拍t3完成
//加法
assign add1 = iadd&&t3;
assign add2 = iadd&&t4;
//减法
assign sub1 = isub&&t3;
assign sub2 = isub&&t4;
//与
assign and1 = iand&&t3;
assign and2 = iand&&t4;
//或
assign or1 = ior&&t3;
assign or2 = ior&&t4;
//异或
assign xor1 = ixor&&t3;
assign xor2 = ixor&&t4;
//自加
assign inc1 = iinc&&t3;
//自减
assign dec1 = idec&&t3;
//清零
assign clr1 = iclr&&t3;
//取非
assign not1 = inot&&t3;
//r0->r1
assign mvr1 = imvr&&t3;
//左移
assign shl1 = ishl&&t3;
//右移
assign shr1 = ishr&&t3;
//M[A]-r0
assign lad1 = ilad&&t3;
assign lad2 = ilad&&t4;
assign lad3 = ilad&&t5;
assign lad4 = ilad&&t6;
assign lad5 = ilad&&t7;
//r0->M[A]
assign sto1 = isto&&t3;
assign sto2 = isto&&t4;
assign sto3 = isto&&t5;
assign sto4 = isto&&t6;
assign sto5 = isto&&t7;
//GOTO A
assign jmp1 = ijmp&&t3;
assign jmp2 = ijmp&&t4;
assign jmp3 = ijmp&&t5;
//IF(Z==1) GOTO A
assign jpz1 = ijpz&&t3;
assign jpz2 = ijpz&&t4;
assign jpz3 = ijpz&&t5;
//IF(Z==0) GOTO A
assign jpnz1= ijpnz&&t3;
assign jpnz2= ijpnz&&t4;
assign jpnz3= ijpnz&&t5;
//状态表达式
assign pcbus = fetch1||fetch3;
assign read = fetch2||lad1||sto1||lad2||sto2||lad4||jmp1||(z&&jpz1)||(!z&&jpnz1)||jmp2||(z&&jpz2)||(!z&&jpnz2);
assign write = sto5;
assign pcinc = fetch2||lad1||lad2||sto1||sto2||(!z&&jpz2)||(!z&&jpz3)||(z&&jpnz2)||(z&&jpnz3);
assign pcload = jmp3||(z&&jpz3)||(!z&&jpnz3);
assign irload = fetch3;
assign r1load = mvr1;
assign busmem = sto5;
assign drlbus = lad5||sto5;
assign r0bus = mvr1||sto4;
assign arload = fetch1||fetch3||lad3||sto3;
assign r1bus = add2||sub2||and2||or2||xor2||shl1||shr1;
assign arinc = lad1||sto1||jmp1||(z&&jpz1)||(!z&&jpnz1);
assign trload = lad2||sto2||jmp2||(z&&jpz2)||(!z&&jpnz2);
assign trbus = lad3||sto3||jmp3||(z&&jpz3)||(!z&&jpnz3);
assign drhbus = lad3||sto3||jmp3||(z&&jpz3)||(!z&&jpnz3);
assign zload = add2||sub2||and2||or2||xor2||shl1||shr1||inc1||dec1||clr1||not1||jmp3||(z&&jpz3)||(!z&&jpnz3)||lad5||sto5;
assign r0load = add2||sub2||and2||or2||xor2||shl1||shr1||inc1||dec1||clr1||not1||lad5;
assign membus = fetch2||lad1||sto1||lad2||sto2||lad4||jmp1||(z&&jpz1)||(!z&&jpnz1)||jmp2||(z&&jpz2)||(!z&&jpnz2);
assign drload = fetch2||lad1||sto1||lad2||sto2||lad4||sto4||jmp1||(z&&jpz1)||(!z&&jpnz1)||jmp2||(z&&jpz2)||(!z&&jpnz2);
assign xload = add1||sub1||and1||or1||xor1;
//alu
reg [3:0]alus;
always@(posedge clk or negedge reset)
begin
if(!reset)
begin//各指令清零,以下已为nop指令清零,请补充其他指令,为其他指令清零
inop<=0;
iadd<=0;
isub<=0;
iand<=0;
ior<=0;
ixor<=0;
iinc<=0;
idec<=0;
iclr<=0;
inot<=0;
ishl<=0;
ishr<=0;
imvr<=0;
ijmp<=0;
ijpz<=0;
ijpnz<=0;
ilad<=0;
isto<=0;
alus<=4'bz;
end
else
begin
//alus初始化为z,加上将alus初始化为x的语句,后续根据不同指令为alus赋值
alus<=4'bx;
if(din[2:0]==000)//译码处理过程
begin
case(din[7:3])
0: begin//指令高5位为0,应该是nop指令,因此这里inop的值是1,而其他指令应该清零,请补充为其他指令清零的语句
inop<=1;
iadd<=0;
isub<=0;
iand<=0;
ior<=0;
ixor<=0;
iinc<=0;
idec<=0;
iclr<=0;
inot<=0;
ishl<=0;
ishr<=0;
imvr<=0;
ijmp<=0;
ijpz<=0;
ijpnz<=0;
ilad<=0;
isto<=0;
end
1: begin
//指令高5位为00001,应该是add指令,因此iadd指令为1,其他指令都应该是0。
//该指令需要做加法运算,详见《示例机的设计Quartus II和使用说明文档》中“ALU的设计”,因此这里要对alus赋值
//后续各分支类似,只有一条指令为1,其他指令为0,以下分支都给出nop指令的赋值,需要补充其他指令,注意涉及到运算的都要对alus赋值
inop<=0;
iadd<=1;
isub<=0;
iand<=0;
ior<=0;
ixor<=0;
iinc<=0;
idec<=0;
iclr<=0;
inot<=0;
ishl<=0;
ishr<=0;
imvr<=0;
ijmp<=0;
ijpz<=0;
ijpnz<=0;
ilad<=0;
isto<=0;
alus<=4'b0001;
end
2: begin
inop<=0;
iadd<=0;
isub<=1;
iand<=0;
ior<=0;
ixor<=0;
iinc<=0;
idec<=0;
iclr<=0;
inot<=0;
ishl<=0;
ishr<=0;
imvr<=0;
ijmp<=0;
ijpz<=0;
ijpnz<=0;
ilad<=0;
isto<=0;
alus<=4'b0010;
end
3: begin
inop<=0;
iadd<=0;
isub<=0;
iand<=1;
ior<=0;
ixor<=0;
iinc<=0;
idec<=0;
iclr<=0;
inot<=0;
ishl<=0;
ishr<=0;
imvr<=0;
ijmp<=0;
ijpz<=0;
ijpnz<=0;
ilad<=0;
isto<=0;
alus<=4'b0011;
end
4: begin
inop<=0;
iadd<=0;
isub<=0;
iand<=0;
ior<=1;
ixor<=0;
iinc<=0;
idec<=0;
iclr<=0;
inot<=0;
ishl<=0;
ishr<=0;
imvr<=0;
ijmp<=0;
ijpz<=0;
ijpnz<=0;
ilad<=0;
isto<=0;
alus<=4'b0100;
end
5: begin
inop<=0;
iadd<=0;
isub<=0;
iand<=0;
ior<=0;
ixor<=1;
iinc<=0;
idec<=0;
iclr<=0;
inot<=0;
ishl<=0;
ishr<=0;
imvr<=0;
ijmp<=0;
ijpz<=0;
ijpnz<=0;
ilad<=0;
isto<=0;
alus<=4'b0101;
end
6: begin
inop<=0;
iadd<=0;
isub<=0;
iand<=0;
ior<=0;
ixor<=0;
iinc<=1;
idec<=0;
iclr<=0;
inot<=0;
ishl<=0;
ishr<=0;
imvr<=0;
ijmp<=0;
ijpz<=0;
ijpnz<=0;
ilad<=0;
isto<=0;
alus<=4'b0110;
end
7: begin
inop<=0;
iadd<=0;
isub<=0;
iand<=0;
ior<=0;
ixor<=0;
iinc<=0;
idec<=1;
iclr<=0;
inot<=0;
ishl<=0;
ishr<=0;
imvr<=0;
ijmp<=0;
ijpz<=0;
ijpnz<=0;
ilad<=0;
isto<=0;
alus<=4'b0111;
end
8: begin
inop<=0;
iadd<=0;
isub<=0;
iand<=0;
ior<=0;
ixor<=0;
iinc<=0;
idec<=0;
iclr<=1;
inot<=0;
ishl<=0;
ishr<=0;
imvr<=0;
ijmp<=0;
ijpz<=0;
ijpnz<=0;
ilad<=0;
isto<=0;
alus<=4'b0000;
end
9: begin
inop<=0;
iadd<=0;
isub<=0;
iand<=0;
ior<=0;
ixor<=0;
iinc<=0;
idec<=0;
iclr<=0;
inot<=1;
ishl<=0;
ishr<=0;
imvr<=0;
ijmp<=0;
ijpz<=0;
ijpnz<=0;
ilad<=0;
isto<=0;
alus<=4'b1000;
end
10:begin
inop<=0;
iadd<=0;
isub<=0;
iand<=0;
ior<=0;
ixor<=0;
iinc<=0;
idec<=0;
iclr<=0;
inot<=0;
ishl<=1;
ishr<=0;
imvr<=0;
ijmp<=0;
ijpz<=0;
ijpnz<=0;
ilad<=0;
isto<=0;
alus<=4'b1001;
end
11:begin
inop<=0;
iadd<=0;
isub<=0;
iand<=0;
ior<=0;
ixor<=0;
iinc<=0;
idec<=0;
iclr<=0;
inot<=0;
ishl<=0;
ishr<=1;
imvr<=0;
ijmp<=0;
ijpz<=0;
ijpnz<=0;
ilad<=0;
isto<=0;
alus<=4'b1010;
end
12:begin
inop<=0;
iadd<=0;
isub<=0;
iand<=0;
ior<=0;
ixor<=0;
iinc<=0;
idec<=0;
iclr<=0;
inot<=0;
ishl<=0;
ishr<=0;
imvr<=1;
ijmp<=0;
ijpz<=0;
ijpnz<=0;
ilad<=0;
isto<=0;
alus<=4'b1011;
end
13:begin
inop<=0;
iadd<=0;
isub<=0;
iand<=0;
ior<=0;
ixor<=0;
iinc<=0;
idec<=0;
iclr<=0;
inot<=0;
ishl<=0;
ishr<=0;
imvr<=0;
ijmp<=1;
ijpz<=0;
ijpnz<=0;
ilad<=0;
isto<=0;
end
14:begin
inop<=0;
iadd<=0;
isub<=0;
iand<=0;
ior<=0;
ixor<=0;
iinc<=0;
idec<=0;
iclr<=0;
inot<=0;
ishl<=0;
ishr<=0;
imvr<=0;
ijmp<=0;
ijpz<=1;
ijpnz<=0;
ilad<=0;
isto<=0;
end
15:begin
inop<=0;
iadd<=0;
isub<=0;
iand<=0;
ior<=0;
ixor<=0;
iinc<=0;
idec<=0;
iclr<=0;
inot<=0;
ishl<=0;
ishr<=0;
imvr<=0;
ijmp<=0;
ijpz<=0;
ijpnz<=1;
ilad<=0;
isto<=0;
end
16:begin
inop<=0;
iadd<=0;
isub<=0;
iand<=0;
ior<=0;
ixor<=0;
iinc<=0;
idec<=0;
iclr<=0;
inot<=0;
ishl<=0;
ishr<=0;
imvr<=0;
ijmp<=0;
ijpz<=0;
ijpnz<=0;
ilad<=1;
isto<=0;
alus<=4'b1011;
end
17:begin
inop<=0;
iadd<=0;
isub<=0;
iand<=0;
ior<=0;
ixor<=0;
iinc<=0;
idec<=0;
iclr<=0;
inot<=0;
ishl<=0;
ishr<=0;
imvr<=0;
ijmp<=0;
ijpz<=0;
ijpnz<=0;
ilad<=0;
isto<=1;
end
default:;
//如果还有分支,可以继续写,如果没有分支了,写上defuault语句
endcase
end
end
end
/*——————8个节拍t0-t7————*/
always @(posedge clk or negedge reset)
begin
if(!reset) //reset清零
begin
t0<=1;
t1<=0;
t2<=0;
t3<=0;
t4<=0;
t5<=0;
t6<=0;
t7<=0;
end
else
begin
if(inc) //运行
begin
t7<=t6;
t6<=t5;
t5<=t4;
t4<=t3;
t3<=t2;
t2<=t1;
t1<=t0;
t0<=0;
end
else if(clr) //清零
begin
t0<=1;
t1<=0;
t2<=0;
t3<=0;
t4<=0;
t5<=0;
t6<=0;
t7<=0;
end
end
end
/*—————结束—————*/
endmodule
cpu.v
/*CPU*/
//省略号中是自行设计的控制信号,需要自行补充
module cpu(data_in,clk_quick,clk_slow,zout,clk_delay,rst,SW_choose,A1,cpustate,
addr,data_out,r0dbus,r1dbus,read,write,arload,arinc,trload,trbus,r1load,r1bus,
r0bus, pcload, pcinc,pcbus,drdbus,membus,busmem, drload,drlbus,drhbus,
r0load,bus,irout, irload,zload,xload,clr);
input[7:0] data_in;
input clk_quick,clk_slow,clk_delay;
input rst;
input SW_choose,A1;
input [1:0] cpustate;
output [15:0] addr;
output [7:0] data_out;
output [7:0] r0dbus;//r0寄存器的输出
output [7:0] r1dbus;//r1寄存器的输出
//补充自行设计的控制信号的端口说明,都是output
output zout,read,write,arload,arinc,trload,trbus,r1load,r1bus,r0bus, pcload,xload;
output pcinc,pcbus,drdbus,membus,busmem, drload,drlbus,drhbus, r0load, bus, irload,zload, clr;
wire[3:0] alus;
wire clk_choose,clk_run;
wire[15:0] dbus,pcdbus;
wire[7:0]drdbus,trdbus,rdbus,r0dbus;
//补充自行设计的控制信号的端口说明,都是output
wire[7:0] aluout;
wire[7:0] xout;
wire zout;//标志位
//定义一些需要的内部信号
output [7:0] irout;
//qtsj(clk_quick,clk_slow,clk_delay,clr,rst,SW_choose,A1,cpustate,clk_run,clk_choose);
qtsj qtdl(.clk_quick(clk_quick),.clk_slow(clk_slow),.clk_delay(clk_delay),.clr(clr),.rst(rst),.SW_choose(SW_choose),.A1(A1),.cpustate(cpustate),.clk_run(clk_run),.clk_choose(clk_choose));
//ar(din, clk, rst,arload, arinc, dout);
ar mar(.din(dbus),.clk(clk_choose),.rst(rst),.arload(arload),.arinc(arinc),.dout(addr));
//pc(din, clk, rst,pcload, pcinc, dout);
pc mpc(.din(dbus),.clk(clk_choose),.rst(rst),.pcload(pcload),.pcinc(pcinc),.dout(pcdbus));
//dr(din, clk,rst, drload, dout);补充dr实例化语句
dr mdr(.din(dbus[7:0]),.clk(clk_choose), .rst(rst), .drload(drload), .dout(drdbus));
//tr(din, clk,rst, trload, dout);补充tr实例化语句,如果需要tr的话
tr mtr(.din(drdbus),.clk(clk_choose), .rst(rst), .trload(trload), .dout(trdbus));
//ir(din,clk,rst,irload,dout);补充ir实例化语句
ir mir(.din(drdbus),.clk(clk_choose), .rst(rst), .irload(irload), .dout(irout));
//r0(din, clk, rst,r0load, dout);补充r0实例化语句
r0 mr0(.din(aluout),.clk(clk_choose), .rst(rst), .r0load(r0load),.dout(r0dbus));
//r1(din, clk, rst,r1load, dout);补充r1实例化语句
r1 mr1(.din(dbus[7:0]),.clk(clk_choose), .rst(rst), .r1load(r1load), .dout(r1dbus));
// x(din, clk, rst,xload, dout);补充x实例化语句
x mx(.din(dbus[7:0]),.clk(clk_choose),.rst(rst),.xload(xload),.dout(xout));
//alu(alus,x, bus, dout);补充alu实例化语句
alu malu(.alus(alus),.x(r0dbus) , .bus(dbus[7:0]), .dout(aluout));
//z(din,clk,rst, zload,dout);补充z实例化语句,如果需要的话
z mz(.din(aluout),.clk(clk_choose), .rst(rst),.zload(zload), .dout(zout));
//control(din,clk,rst,z,cpustate,read,...,clr);补充control实例化语句
//control mcontrol(.din(irout),.clk(clk_run),.rst(rst),.z(zout),.cpustate(cpustate),
//,.read(read),.write(write),.membus(membus),.busmem(busmem),.arload(arload),.arinc(arinc),.pcload(pcload),
//.pcinc(pcinc), .pcbus(pcbus),.drload(drload),.drbus(drbus),.trload(trload),.trbus(trbus),.irload(irload),.r1load(r1load),.r1bus(r1bus),
//.alus(alus),.zload(zload),.r0load(r0load),.r0bus(r0bus),.drhbus(drhbus), .drlbus(drlbus),.xload(xload),.clr(clr));
control mcontrol(.din(irout),.clk(clk_choose),.rst(rst),.z(zout),.cpustate(cpustate),.alus(alus),.irload(irload),.r1load(r1load),.r1bus(r1bus),
.zload(zload),.xload(xload),.r0load(r0load),.r0bus(r0bus),.read(read),.write(write),.membus(membus),.busmem(busmem),.arload(arload),.arinc(arinc),
.pcload(pcload),.pcinc(pcinc),.pcbus(pcbus),.drload(drload),.drbus(drbus),.trload(trload),.trbus(trbus),.drhbus(drhbus),.drlbus(drlbus),.clr(clr));
//allocate dbus
assign dbus[15:0]=(pcbus)?pcdbus[15:0]:16'bzzzzzzzzzzzzzzzz;
assign dbus[15:8]=(drhbus)?drdbus[7:0]:8'bzzzzzzzz;
assign dbus[7:0]=(drlbus)?drdbus[7:0]:8'bzzzzzzzz;
//如果需要tr的话,补充dbus接收tr的输出trdbus
assign dbus[7:0]=(trbus)?trdbus[7:0]:8'bzzzzzzzz;
assign dbus[7:0]=(r1bus)?r1dbus[7:0]:8'bzzzzzzzz;
assign dbus[7:0]=(r0bus)?r0dbus[7:0]:8'bzzzzzzzz;
assign dbus[7:0]=(membus)?data_in[7:0]:8'bzzzzzzzz;
assign data_out=(busmem)?dbus[7:0]:8'bzzzzzzzz;
endmodule
dr.v
/*数据寄存器,存放双指令中低8位指向地址的存放值*/
module dr(din, clk,rst, drload, dout);
input [7:0] din;
input clk, rst, drload;
output [7:0] dout;
reg [7:0]dout;
always @(posedge clk or negedge rst)
if(!rst)
dout<=0;
else if(drload)
dout<=din;
endmodule
ir.v
/*指令寄存器,存储要执行的指令*/
//注意:该寄存器是时钟的下降沿有效
module ir(din,clk,rst,irload,dout);
input [7:0]din;
input clk, rst, irload;
output [7:0]dout;
reg [7:0]dout;
always @(negedge clk or negedge rst )
if(!rst) dout<=0;
else if(irload) dout<=din;
endmodule
light_show.v
/*灯光显示单元,通过HEX6-HEX0:7个数码管进行显示*/
/*输入light_clk:light的时钟信号,1位;来自于top.v的分频器clk_div的输出clk_light;
输入SW_choose:选择快慢;1位;在top.v的端口;
输入check_in:8位;来自于存储器的check_out,CPU为check状态下的输出;
输入read——clr:为控制信号,都是1位,来自控制器;
输入State:CPU的状态,2位;来自CPU_Controller的输出;
输入MAR:地址;8位,来自cpu.v的输出addr的低8位;用hex0和hex1显示
输入r0:r0寄存器的结果显示;来自于r0寄存器的输出r0dbus;用hex4和hex5显示
输入r1:r1寄存器的结果显示;来自于r1寄存器的输出r1dbus;用hex2和hex3显示
输入Z:z标志寄存器的结果显示:来自z寄存器的输出;用hex6显示
输出HEX0-HEX7:为8个数码管
*/
module light_show (light_clk,SW_choose,check_in,State,MAR,
r0,r1,Z,HEX0,HEX1,HEX2,HEX3,HEX4,HEX5,HEX6,HEX7,State_LED,quick_low_led,arload,arinc,
pcinc,pcload,drload,trload,irload,r1load,r0load,zload,xload,pcbus,
drhbus,drlbus,trbus,r1bus,r0bus,membus,busmem,clr,
read_led,write_led,arload_led,arinc_led,pcinc_led,pcload_led,
drload_led,trload_led,irload_led,r1load_led,r0load_led,zload_led,xload_led,
pcbus_led,drhbus_led,drlbus_led,trbus_led,r1bus_led,r0bus_led,
membus_led,busmem_led,clr_led,read,write);
input light_clk;
input SW_choose;
input [7:0] check_in;
input arload,arinc,
pcinc,pcload,drload,trload,irload,r1load,r0load,zload,xload,pcbus,
drhbus,drlbus,trbus,r1bus,r0bus,membus,busmem,read,write,clr;
input [1:0] State; //状态,LEDG1~LEDG3
input [7:0] MAR; //下一执行指令地址:hex0,1
input [7:0] r0,r1; //r0通用寄存器运行结果显示,hex4,5;r1通用寄存器结果显示,hex2,3
input Z; //标志寄存器Z的值,hex6
output reg [6:0] HEX0;
output reg [6:0] HEX1;
output reg [6:0] HEX2;
output reg [6:0] HEX3;
output reg [6:0] HEX4;
output reg [6:0] HEX5;
output reg [6:0] HEX6;
output [6:0] HEX7;
output [1:0] State_LED;
output quick_low_led;
output read_led,write_led,arload_led,arinc_led,pcinc_led,pcload_led,
drload_led,trload_led,irload_led,r1load_led,r0load_led,zload_led,xload_led,
pcbus_led,drhbus_led,drlbus_led,trbus_led,r1bus_led,r0bus_led,
membus_led,busmem_led,clr_led;
assign HEX7 = 7'b0111111;
assign read_led=read;
assign write_led=write;
assign arload_led=arload;
assign arinc_led=arinc;
assign pcinc_led=pcinc;
assign pcload_led=pcload;
assign zload_led=zload;
assign xload_led=xload;
assign pcbus_led=pcbus;
assign drload_led=drload;
assign trload_led=trload;
assign irload_led=irload;
assign r1load_led=r1load;
assign r0load_led=r0load;
assign drhbus_led=drhbus;
assign drlbus_led=drlbus;
assign membus_led=membus;
assign busmem_led=busmem;
assign trbus_led=trbus;
assign r1bus_led=r1bus;
assign r0bus_led=r0bus;
assign clr_led=clr;
//always @(posedge light_clk or negedge K6 or posedge STP)
always @(posedge light_clk)
begin
begin
case(MAR[3:0]) //hex0
4'd0:HEX0 <= 7'b1000000;
4'd1:HEX0 <= 7'b1111001;
4'd2:HEX0 <= 7'b0100100;
4'd3:HEX0 <= 7'b0110000;
4'd4:HEX0 <= 7'b0011001;
4'd5:HEX0 <= 7'b0010010;
4'd6:HEX0 <= 7'b0000010;
4'd7:HEX0 <= 7'b1111000;
4'd8:HEX0 <= 7'b0000000;
4'd9:HEX0 <= 7'b0010000;
4'd10:HEX0 <= 7'b0011000;//a
4'd11:HEX0 <= 7'b0000011;//b
4'd12:HEX0 <= 7'b0100111;//c
4'd13:HEX0 <= 7'b0100001;//d
4'd14:HEX0 <= 7'b0000100;//e
4'd15:HEX0 <= 7'b0001111;//f
default:HEX0 <= 7'b0111111;
endcase
case(MAR[7:4]) //hex1
4'd0:HEX1 <= 7'b1000000;
4'd1:HEX1 <= 7'b1111001;
4'd2:HEX1 <= 7'b0100100;
4'd3:HEX1 <= 7'b0110000;
4'd4:HEX1 <= 7'b0011001;
4'd5:HEX1 <= 7'b0010010;
4'd6:HEX1 <= 7'b0000010;
4'd7:HEX1 <= 7'b1111000;
4'd8:HEX1 <= 7'b0000000;
4'd9:HEX1 <= 7'b0010000;
4'd10:HEX1 <= 7'b0011000;//a
4'd11:HEX1 <= 7'b0000011;//b
4'd12:HEX1 <= 7'b0100111;//c
4'd13:HEX1 <= 7'b0100001;//d
4'd14:HEX1 <= 7'b0000100;//e
4'd15:HEX1 <= 7'b0001111;//f
default:HEX1 <= 7'b0111111;
endcase
case(Z) //hex6
4'd0:HEX6 <= 7'b1000000;
4'd1:HEX6 <= 7'b1111001;
default:HEX6 <= 7'b0111111;
endcase
case(r0[3:0]) //hex4
4'd0:HEX4 <= 7'b1000000;
4'd1:HEX4 <= 7'b1111001;
4'd2:HEX4 <= 7'b0100100;
4'd3:HEX4 <= 7'b0110000;
4'd4:HEX4 <= 7'b0011001;
4'd5:HEX4 <= 7'b0010010;
4'd6:HEX4 <= 7'b0000010;
4'd7:HEX4 <= 7'b1111000;
4'd8:HEX4 <= 7'b0000000;
4'd9:HEX4 <= 7'b0010000;
4'd10:HEX4 <= 7'b0011000;//a
4'd11:HEX4 <= 7'b0000011;//b
4'd12:HEX4 <= 7'b0100111;//c
4'd13:HEX4 <= 7'b0100001;//d
4'd14:HEX4 <= 7'b0000100;//e
4'd15:HEX4 <= 7'b0001111;//f
default:HEX4 <= 7'b0111111;
endcase
case(r0[7:4]) //hex5
4'd0:HEX5 <= 7'b1000000;
4'd1:HEX5 <= 7'b1111001;
4'd2:HEX5 <= 7'b0100100;
4'd3:HEX5 <= 7'b0110000;
4'd4:HEX5 <= 7'b0011001;
4'd5:HEX5 <= 7'b0010010;
4'd6:HEX5 <= 7'b0000010;
4'd7:HEX5 <= 7'b1111000;
4'd8:HEX5 <= 7'b0000000;
4'd9:HEX5 <= 7'b0010000;
4'd10:HEX5 <= 7'b0011000;//a
4'd11:HEX5 <= 7'b0000011;//b
4'd12:HEX5 <= 7'b0100111;//c
4'd13:HEX5 <= 7'b0100001;//d
4'd14:HEX5 <= 7'b0000100;//e
4'd15:HEX5 <= 7'b0001111;//f
default:HEX5 <= 7'b0111111;
endcase
case(r1[3:0]) //hex2
4'd0:HEX2 <= 7'b1000000;
4'd1:HEX2 <= 7'b1111001;
4'd2:HEX2 <= 7'b0100100;
4'd3:HEX2 <= 7'b0110000;
4'd4:HEX2 <= 7'b0011001;
4'd5:HEX2 <= 7'b0010010;
4'd6:HEX2 <= 7'b0000010;
4'd7:HEX2 <= 7'b1111000;
4'd8:HEX2 <= 7'b0000000;
4'd9:HEX2 <= 7'b0010000;
4'd10:HEX2 <= 7'b0011000;//a
4'd11:HEX2 <= 7'b0000011;//b
4'd12:HEX2 <= 7'b0100111;//c
4'd13:HEX2 <= 7'b0100001;//d
4'd14:HEX2 <= 7'b0000100;//e
4'd15:HEX2 <= 7'b0001111;//f
default:HEX2 <= 7'b0111111;
endcase
case(r1[7:4]) //hex3
4'd0:HEX3 <= 7'b1000000;
4'd1:HEX3 <= 7'b1111001;
4'd2:HEX3 <= 7'b0100100;
4'd3:HEX3 <= 7'b0110000;
4'd4:HEX3 <= 7'b0011001;
4'd5:HEX3 <= 7'b0010010;
4'd6:HEX3 <= 7'b0000010;
4'd7:HEX3 <= 7'b1111000;
4'd8:HEX3 <= 7'b0000000;
4'd9:HEX3 <= 7'b0010000;
4'd10:HEX3 <= 7'b0011000;//a
4'd11:HEX3 <= 7'b0000011;//b
4'd12:HEX3 <= 7'b0100111;//c
4'd13:HEX3 <= 7'b0100001;//d
4'd14:HEX3 <= 7'b0000100;//e
4'd15:HEX3 <= 7'b0001111;//f
default:HEX3 <= 7'b0111111;
endcase
end
end
assign State_LED = State; //显示状态灯
assign quick_low_led = SW_choose;//快慢时钟灯
endmodule
pc.v
/*程序计数器,输出当前执行的指令地址
可仿照ar地址寄存器来写,注意替换控制信号*/
module pc(din, clk, rst,pcload, pcinc, dout);
input [15:0]din;
input clk,rst,pcload,pcinc;
output reg[15:0]dout;
always@(posedge clk or negedge rst)
begin
if(!rst)
dout <= 0;
else if(pcload)
dout <= din;
else if(pcinc)
dout <= dout + 1;
end
endmodule
r0.v
/*r0通用寄存器*/
module r0(din, clk, rst,r0load, dout);
input [7:0] din;
input clk,rst,r0load;
output reg [7:0] dout;
always @(posedge clk or negedge rst)
begin
if (!rst)
dout <= 0;
else if (r0load)
dout <= din;
end
endmodule
r1.v
/*r1通用寄存器*/
module r1(din, clk, rst,r1load, dout);
input [7:0] din;
input clk,rst,r1load;
output reg [7:0] dout;
always @(posedge clk or negedge rst)
begin
if (!rst)
dout <= 0;
else if (r1load)
dout <= din;
end
endmodule
top.v
//the relatively complex cpu
//design by cgy,2020.11
//modify by zhy,2022.11
//实例化,将分频模块,cpu模块,存储器模块,显示模块连接到一起。
module top(clk,rst,A1,SW_choose,SW1,SW2,D,addr,rambus,data,HEX0,HEX1,HEX2,HEX3,HEX4,HEX5,HEX6,HEX7,r0dbus,r1dbus,cpustate_led,
check_out,quick_low_led,read_led,write_led,arload_led,arinc_led,pcinc_led,pcload_led,drload_led,trload_led,irload_led,
r1load_led,r0load_led,zload_led,xload_led,pcbus_led,drhbus_led,drlbus_led,trbus_led,r1bus_led,r0bus_led,membus_led,busmem_led,
clr_led);
input clk, rst;
input A1;
input SW_choose,SW1,SW2;
input [7:0] D;
//output[7:0]data;
output[15:0]addr;
output [7:0]rambus;
output [7:0] data;
output [6:0] HEX0,HEX1,HEX2,HEX3,HEX4,HEX5,HEX6,HEX7;
output [7:0] r0dbus;//r0通用寄存器的输出
output [7:0] r1dbus;//r1通用寄存器的输出
output [1:0] cpustate_led;
output [7:0] check_out;
output quick_low_led;
output read_led,write_led,arload_led,arinc_led,pcinc_led,pcload_led,drload_led,trload_led,irload_led,r1load_led,r0load_led,zload_led,xload_led,pcbus_led,drhbus_led,drlbus_led,trbus_led,r1bus_led,r0bus_led,membus_led,busmem_led,clr_led;
wire [7:0]X;
wire Z;
wire read,write,arload,arinc,pcinc,pcload,drload,trload,irload,r1load,r0load,irout,zload,xload,pcbus,drhbus,drlbus,trbus,r1bus,r0bus,membus,busmem,clr;
wire clk_quick,clk_slow,clk_delay,clk_mem,clk_light;
wire [1:0] cpustate;
/*----------分频程序---------------*/
//综合用
//clk_div quick(.clk(clk),.reset(rst),.symbol(32'd16384000),.div_clk(clk_quick));
//clk_div slow(.clk(clk),.reset(rst),.symbol(32'd49152000),.div_clk(clk_slow));
//clk_div delay(.clk(clk),.reset(rst),.symbol(32'd2048000),.div_clk(clk_delay));
//clk_div mem(.clk(clk),.reset(rst),.symbol(32'd2048000),.div_clk(clk_mem));
//clk_div light(.clk(clk),.reset(rst),.symbol(32'd2048000),.div_clk(clk_light));
//仿真用
clk_div quick(.clk(clk),.reset(rst),.symbol(32'd3),.div_clk(clk_quick));
clk_div slow(.clk(clk),.reset(rst),.symbol(32'd6),.div_clk(clk_slow));
clk_div delay(.clk(clk),.reset(rst),.symbol(32'd1),.div_clk(clk_delay));
clk_div mem(.clk(clk),.reset(rst),.symbol(32'd3),.div_clk(clk_mem));
clk_div light(.clk(clk),.reset(rst),.symbol(32'd3),.div_clk(clk_light));
/*-------------------------------*/
/*CPU_Controller(SW1,SW2,CPU_state);*/
CPU_Controller controller(.SW1(SW1),.SW2(SW2),.CPU_state(cpustate));
//补充cpu实例化的语句
cpu mcpu(.data_in(rambus),.clk_quick(clk_quick),.clk_slow(clk_slow),.clk_delay(clk_delay),.zout(Z),
.rst(rst),.SW_choose(SW_choose),.A1(A1),.cpustate(cpustate),.addr(addr),.data_out(data),.r0dbus(r0dbus),
.r1dbus(r1dbus),.read(read),.write(write),.arload(arload),.arinc(arinc),.trload(trload),.trbus(trbus),
.r1load(r1load),.r1bus(r1bus),.r0bus(r0bus), .pcload(pcload), .pcinc(pcinc),.pcbus(pcbus),.drdbus(drdbus),
.membus(membus),.busmem(busmem), .drload(drload),.drlbus(drlbus),.drhbus(drhbus), .r0load(r0load),
.bus(dbus),.irout(irout), .irload(irload),.zload(zload),.xload(xload),.clr(clr));
/*ram(clk,data_in,addr,A1,reset,read,write,cpustate,D,data_out,check_out);*/
ram mm(.clk(clk_mem),.data_in(data),.addr(addr),.A1(A1),.reset(rst),.read(read),.write(write),.cpustate(cpustate),.D(D),.data_out(rambus),.check_out(check_out));
/*light_show(light_clk,SW_choose,check_in,read,write,arload,arinc,pcinc,pcload,drload,trload,irload,r1load,r0load,zload,pcbus,drhbus,drlbus,trbus,r1bus,r0bus,membus,busmem,clr,State,MAR,r0,R,Z,HEX0,HEX1,HEX2,HEX3,HEX4,HEX5,HEX6,HEX7,State_LED,quick_low_led,read_led,write_led,arload_led,arinc_led,pcinc_led,pcload_led,drload_led,trload_led,irload_led,r1load_led,r0load_led,zload_led,pcbus_led,drhbus_led,drlbus_led,trbus_led,r1bus_led,r0bus_led,membus_led,busmem_led,clr_led);*/
light_show show(.light_clk(clk_light),.SW_choose(SW_choose),.check_in(check_out),.State(cpustate),.MAR(addr[7:0]),
.r0(r0dbus),.r1(r1dbus),.Z(Z),.HEX0(HEX0),.HEX1(HEX1),.HEX2(HEX2),.HEX3(HEX3),.HEX4(HEX4),.HEX5(HEX5),.HEX6(HEX6),
.HEX7(HEX7),.State_LED(cpustate_led),.quick_low_led(quick_low_led), .arload(arload), .arinc(arinc),
.pcinc(pcinc),.pcload(pcload),.drload(drload),.trload(trload),.irload(irload),.r1load(r1load),.r0load(r0load),.zload(zload),.xload(xload),.pcbus(pcbus),
.drhbus(drhbus),.drlbus(drlbus),.trbus(trbus),.r1bus(r1bus),.r0bus(r0bus),.membus(membus),.busmem(busmen),.clr(clr),
.read_led(read_led),.write_led(write_led),.arload_led(arload_led),.arinc_led(arinc_led),.pcinc_led(pcinc_led),.pcload_led(pcload_led),
.drload_led(drload_led),.trload_led(trload_led),.irload_led(irload_led),.r1load_led(r1load_led),.r0load_led(r0load_led),.zload_led(zload_led),.xload_led(xload_led),
.pcbus_led(pcbus_led),.drhbus_led(drhbus_led),.drlbus_led(drlbus_led),.trbus_led(trbus_led),.r1bus_led(r1bus_led),.r0bus_led(r0bus_led),
.membus_led(membus_led),.busmem_led(busmem_led),.clr_led(clr_led),.read(read),.write(write));
endmodule
tr.v
/*数据暂存器,处理双字节指令时使用,用来存储低八位的地址或数值*/
module tr(din, clk,rst, trload, dout);
input [7:0] din;
input clk, rst, trload;
output [7:0] dout;
reg [7:0]dout;
always @(posedge clk or negedge rst)
begin
if(!rst)
dout<=0;
else if(trload)
dout<=din;
end
endmodule
x.v
/*数据暂存器x,存放ALU的一个输入,另外一个输入来自于总线*/
module x(din, clk, rst,xload, dout);
input clk,rst,xload;
input [7:0] din;
output reg[7:0]dout;
always@(posedge clk or negedge rst)
begin
if(rst==0)
dout <= 0;
else if(xload)
dout <= din;
end
endmodule
z.v
/*标志寄存器*/
module z(din,clk,rst, zload,dout);
input [7:0] din;
input clk, rst, zload;
output dout;
reg dout;
always @(posedge clk or negedge rst)
if(!rst)
dout<=0;
else if(zload)
begin
if(din==8'b00000000)
dout<=1;
else
dout<=0;
end
endmodule