BFU/BJFU 北林计算机组成原理-课程设计

课程设计内容

设计实现一个字长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必做)

  1. 双操作数算术运算指令:ADD、SUB ;R0和R1运算,结果送R0
  2. 双操作数逻辑运算指令:AND、OR、XOR ;R0和R1运算,结果送R0
  3. 单操作数指令:INC、DEC、NOT ;对R0运算,结果送R0
  4. 清零指令(无操作数):CLR ;R0<—0

(3)移位指令:(实现1条

  1. SHR、SHL ;对R0运算,结果送R0

(4)寄存器-寄存器传送指令

  1. MVR R1<—R0

(5)无条件跳转指令:JMP  A(选做) ;A为跳转到的地址

(6)条件跳转指令:(选做)

  1. JPZ A ;z=1时跳转,A为跳转到的地址
  2. JPNZ A ;z=0时跳转,A为跳转到的地址

注意需要加零标志寄存器Z

(7)寄存器-存储器数据传送(选做)

  1. LAD A ;R0<—M[A]
  2. 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

当时的模拟软件

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值