zoukankan      html  css  js  c++  java
  • verilog实现的16位CPU设计

    verilog实现的16位CPU设计


    整体电路图

    整体电路图

    整体电路图

    CPU状态图

    CPU状态图

    idle代表没有工作,exec代表在工作

    实验设计思路

    五级流水线,增加硬件消耗换取时间的做法。
    具体每一部分写什么将由代码部分指明。

    完整代码

    headfile.v

    头文件定义。包含整个工程中的特殊变量定义。后文中只用到gr0到gr3部分,因此该部分没写gr4到gr7,有需要的同学请自行加上。

    `ifndef HEADFILE_H_
    
    //State for CPU
    `define	idle		1'b0
    `define	exec		1'b1
    
    //Data transfer & Arithmetic
    `define  NOP		5'b00000
    `define  HALT		5'b00001
    `define  LOAD		5'b00010
    `define  STORE		5'b00011
    `define  LDIH		5'b10000
    `define  ADD		5'b01000
    `define	ADDI		5'b01001
    `define	ADDC		5'b10001
    `define	CMP		5'b01100
    
    //Logical / shift
    `define	AND		5'b01101
    `define	SLL		5'b00100
    `define	SLA		5'b00101
    
    //Control
    `define	JUMP		5'b11000
    `define	JMPR		5'b11001
    `define	BZ			5'b11010
    `define	BNZ		5'b11011
    `define	BN			5'b11100
    `define	BC			5'b11110
    
    //Add by myself
    `define	SUB   	5'b01010
    `define 	SUBI  	5'b01011
    `define 	SUBC  	5'b10010
    `define 	OR    	5'b01110
    `define 	XOR   	5'b01111
    `define 	SRL   	5'b00110
    `define 	SRA   	5'b00111
    `define 	BNN   	5'b11101
    `define 	BNC   	5'b11111
    
    //gr
    `define gr0 3'b000
    `define gr1 3'b001
    `define gr2 3'b010
    `define gr3 3'b011
    
    `endif
    

    CPU.v

    这个是整个工程的顶层模块。输入100MHz时钟信号,四个开关选择控制七段译码管显示的内容,用button来控制CPU的一次流水线。
    首先三个部分的时钟快慢要求不一样。七段译码器的时钟要求最快,要实时显示内容;memory的时钟要求较快,在PCPU下一级流水线到来之前完成数据读写。PCPU模块的时钟要求最慢,这个只是相对前面来说较慢。整个CPU的工作频率是比较快的。

    `timescale 1ns / 1ps
    
    module CPU(
    	input clk,
    	input enable,
    	input reset,
    	input [3:0] SW,
    	input start,
    	input button,
    	output [6:0] light,
    	output [3:0] en
        );
    
    	wire PCPU_clk;
    	wire MEM_clk;
    	wire LIGHT_clk;
    	
    	wire [15:0] d_datain;
    	wire [15:0] i_datain;
    	wire [3:0] select_y;
    	wire [7:0] d_addr;
    	wire [15:0] d_dataout;
    	wire d_we;
    	wire [7:0] i_addr;
    	wire [15:0] y;
    	
    	clk_div getMEMclk(
    		.orgin_clk(clk),
    		.reset(reset),
    		.div(16'b0100_0000_0000_0000),
    		.div_clk(MEM_clk)
    	);
    	
    	clk_div getLIGHTclk(
    		.orgin_clk(clk),
    		.reset(reset),
    		.div(16'b0010_0000_0000_0000),
    		.div_clk(LIGHT_clk)
    	);
    	
    	PCPUcontroller PCPUctrl(
    		.myclk(clk),
    		.button(button),
    		.reset(reset),
    		.sense(PCPU_clk)
    	);
    	
    	PCPU pcpu(
    		.clock(PCPU_clk),
    		.enable(enable),
    		.reset(reset),
    		.start(start),
    		.d_datain(d_datain),
    		.i_datain(i_datain),
    		.select_y(SW),
    		.d_addr(d_addr),
    		.d_dataout(d_dataout),
    		.d_we(d_we),
    		.i_addr(i_addr),
    		.y(y)
    	);
    	
    	I_mem i_mem(
    		.mem_clk(MEM_clk),
    		.addr(i_addr),
    		.rdata(i_datain)
    	);
    	
    	D_mem d_mem(
    		.mem_clk(MEM_clk),
    		.dwe(d_we),
    		.addr(d_addr),
    		.wdata(d_dataout),
    		.rdata(d_datain)
    	);
    	
    	light_show show_light(
    		.light_clk(LIGHT_clk),
    		.reset(reset),
    		.y(y),
    		.light(light),
    		.en(en)
    	);
    
    endmodule
    

    clk_div.v

    时钟分频模块,要是开始做CPU设计了还不会时钟分频的话,那我没话说了。不解释,贴代码。

    `timescale 1ns / 1ps
    
    module clk_div(
    	input orgin_clk,
    	input reset,
    	input [15:0] div,
    	output reg div_clk
        );
    	
    	reg [15:0] count;
    	
    	always@(posedge orgin_clk or posedge reset)
    	begin
    		if(reset)
    		begin
    			div_clk <= 0;
    			count <= 0;
    		end
    		else
    		begin
    			if(count == div)
    			begin
    				div_clk <= ~div_clk;
    				count <= 0;
    			end
    			else
    				count <= count + 1'b1;
    		end
    	end
    
    
    endmodule
    

    PCPUcontroller.v

    PCPU模块的状态控制模块。因为用的button来手动控制CPU的流水线,以免时钟太快一下子就跑完了。实现的方法是用状态机,加入trap状态,实现消抖。具体想不明白的话,建议自己画一下状态机转移图,聪明的你一定会明白的。

    `timescale 1ns / 1ps
    
    module PCPUcontroller(
    	input myclk,
    	input button,
    	input reset,
    	output reg sense
        );
    
    	parameter STOP = 2'b00, INC = 2'b01, TRAP = 2'b10;
    	
    	reg [1:0] state, nextstate;
    	
    	always@(posedge myclk or posedge reset)
    	begin
    		if(reset)
    			state <= STOP;
    		else
    			state <= nextstate;
    	end
    	
    	always@(*)
    	begin
    		case(state)
    			STOP:
    				if(button)	nextstate <= INC;
    				else			nextstate <= STOP;
    			INC:				nextstate <= TRAP;
    			TRAP:
    				if(button)	nextstate <= TRAP;
    				else			nextstate <= STOP;
    			default:			nextstate <= STOP;
    		endcase
    	end
    	
    	always@(*)
    	begin
    		if(reset)
    			sense <= 0;
    		else
    			case(state)
    				INC:		sense <= 1'b1;
    				default:	sense <= 1'b0;
    			endcase
    	end
    
    endmodule
    

    PCPU.v

    整个工程中最核心的部分。注释部分是冲突处理之后的。如不需要冲突处理,把注释部分指明的代码注释掉即可。对应于前图中的五级流水线,该部分的代码亦分为五部分,请自行研啃。

    `timescale 1ns / 1ps
    `include"headfile.v"
    
    module PCPU(
    	input clock,
    	input enable,
    	input reset,
    	input start,
    	input [15:0] d_datain,
    	input [15:0] i_datain,
    	input [3:0] select_y,
    	output wire [7:0] d_addr,
    	output wire [15:0] d_dataout,
    	output wire d_we,
    	output wire [7:0] i_addr,
    	output reg [15:0] y
        );
    
    	reg state;
    	reg [7:0] pc;
    	reg [15:0] id_ir;
    	reg [15:0] ex_ir, reg_A, reg_B, smdr;
    	reg [15:0] mem_ir, reg_C, smdr1; reg dw; reg flag; reg [15:0] ALUo;reg zf, nf, cf;
    	reg [15:0] wb_ir, reg_C1;
    	
    	reg [15:0] gr[0:7];
    	
    	assign d_dataout = smdr1;
    	assign d_we = dw;
    	assign d_addr = reg_C[7:0];
    	assign i_addr = pc;
    	
    	/*******CPUcontrol**********************/
    	reg nextstate;
    	
    	always@(posedge clock or posedge reset)
    	begin
    		if(reset)
    			state <= `idle;
    		else
    			state <= nextstate;
    	end
    	
    	always@(*)
    	begin
    		case(state)
    			`idle:
    				if((enable == 1'b1) && (start == 1'b1))
    					nextstate <= `exec;
    				else
    					nextstate <= `idle;
    			`exec:
    				if((enable == 1'b0) || (wb_ir[15:11] == `HALT))
    					nextstate <= `idle;
    				else
    					nextstate <= `exec;
    		endcase
    	end
    	
    	/***************************************/
    	
    	/****************IF*********************/
    	always@(posedge clock or posedge reset)
    	begin
    		if(reset)
    		begin
    			id_ir <= 16'b0000_0000_0000_0000;
    			pc <= 8'b0000_0000;
    		end
    		else if(state == `exec)
    		begin
    			/*************Hazard*******************/
    			if((id_ir[15:11] == `LOAD)
    			 &&(i_datain[15:11] == `ADD) 
    			 &&((id_ir[10:8] == i_datain[7:4]) 
    			  ||(id_ir[10:8] == i_datain[3:0])))
    			begin
    				id_ir <= 16'bxxxx_xxxx_xxxx_xxxx;
    				pc <= pc;
    			end
    			/**************************************/
    			else
    			begin
    				id_ir <= i_datain;
    				if(((mem_ir[15:11] == `BZ)  && (zf == 1'b1))
    				 ||((mem_ir[15:11] == `BN)  && (nf == 1'b1))
    				 ||((mem_ir[15:11] == `BC)  && (cf == 1'b1))
    				 ||((mem_ir[15:11] == `BNZ) && (zf == 1'b1))
    				 ||((mem_ir[15:11] == `BNN) && (nf == 1'b1))
    				 ||((mem_ir[15:11] == `BNZ) && (cf == 1'b1)))
    					pc <= reg_C[7:0];
    				else if((mem_ir[15:11] == `JUMP)
    						||(mem_ir[15:11] == `JMPR))
    					pc <= reg_C[7:0];
    				else
    					pc <= pc + 1'b1;
    			end
    		end
    		else
    		begin
    			pc <= pc;
    			id_ir <= id_ir;
    		end
    	end
    	
    	/***************************************/
    	
    	/****************ID*********************/
    	always@(posedge clock or posedge reset)
    	begin
    		if(reset)
    		begin
    			ex_ir <= 16'b0000_0000_0000_0000;
    			reg_A <= 16'b0000_0000_0000_0000;
    			reg_B <= 16'b0000_0000_0000_0000;
    			smdr <= 16'b0000_0000_0000_0000;
    		end
    		else if(state == `exec)
    		begin
    			ex_ir <= id_ir;
    			if(id_ir[15:11] == `STORE)	//for Hazard Mode
    				smdr <= ALUo;
    			//reg_A
    			/********************Hazard**********************/
    			if(wb_ir[15:11] == `LOAD && id_ir[7:4] == wb_ir[10:8])
    				reg_A <= reg_C1;
    			else if(mem_ir[15:11] == `LOAD && id_ir[7:4] == mem_ir[10:8])
    				reg_A <= d_datain;
    			else if(ex_ir[15:11] != `LOAD && id_ir[7:4] == ex_ir[10:8])
    				reg_A <= ALUo;
    			else if(mem_ir[15:11] != `LOAD && id_ir[7:4] == mem_ir[10:8])
    				reg_A <= reg_C;	
    			else if(wb_ir[15:11] != `LOAD && id_ir[7:4] == wb_ir[10:8])
    				reg_A <= reg_C1;
    			else
    			begin
    			/***********************************************/
    				if((id_ir[15:11] == `BZ)
    				 ||(id_ir[15:11] == `BN)
    				 ||(id_ir[15:11] == `JMPR)
    				 ||(id_ir[15:11] == `BC)
    				 ||(id_ir[15:11] == `BNZ)
    				 ||(id_ir[15:11] == `BNN)
    				 ||(id_ir[15:11] == `BNC)
    				 ||(id_ir[15:11] == `ADDI)
    				 ||(id_ir[15:11] == `SUBI)
    				 ||(id_ir[15:11] == `LDIH))
    					reg_A <= gr[(id_ir[10:8])];
    				else
    					reg_A <= gr[(id_ir[6:4])];
    			end
    			//reg_B
    			/********************Hazard*********************/
    			if(wb_ir[15:11] == `LOAD && id_ir[3:0] == wb_ir[10:8])
    				reg_B <= reg_C1;
    			else if(mem_ir[15:11] == `LOAD && id_ir[3:0] == mem_ir[10:8])
    				reg_B <= d_datain;
    			else if(ex_ir[15:11] != `LOAD && id_ir[3:0] == ex_ir[10:8])
    				reg_B <= ALUo;
    			else if(mem_ir[15:11] != `LOAD && id_ir[3:0] == mem_ir[10:8])
    				reg_B <= reg_C;
    			else if(wb_ir[15:11] != `LOAD && id_ir[3:0] == wb_ir[10:8])
    				reg_B <= reg_C1;	
    			else
    			begin
    			/***********************************************/
    				if((id_ir[15:11] == `LOAD)
    				 ||(id_ir[15:11] == `SLL)
    				 ||(id_ir[15:11] == `SLA)
    				 ||(id_ir[15:11] == `SRL)
    				 ||(id_ir[15:11] == `SRA))
    					reg_B <= {12'b0000_0000_0000, id_ir[3:0]};
    				else if((id_ir[15:11] == `BZ)
    						||(id_ir[15:11] == `BN)
    						||(id_ir[15:11] == `JUMP)
    						||(id_ir[15:11] == `JMPR)
    						||(id_ir[15:11] == `BC)
    						||(id_ir[15:11] == `BNZ)
    						||(id_ir[15:11] == `BNN)
    						||(id_ir[15:11] == `BNC)
    						||(id_ir[15:11] == `ADDI))
    					reg_B <= {8'b0000_0000, id_ir[7:0]};
    				else if((id_ir[15:11] == `STORE))
    				begin
    					reg_B <= {12'b0000_0000_0000, id_ir[3:0]};
    					//smdr <= gr[(id_ir[10:8])];	//for not Hazard
    				end
    				else if(id_ir[15:11] == `LDIH)
    					reg_B <= {id_ir[7:0], 8'b0000_0000};
    				else
    					reg_B <= gr[id_ir[2:0]];
    			end
    		end
    		else
    		begin
    			ex_ir <= ex_ir;
    			reg_A <= reg_A;
    			reg_B <= reg_B;
    			smdr <= smdr;
    		end
    	end
    	/***************************************/
    	
    	/****************EX*********************/
    	always@(posedge clock or posedge reset)
    	begin
    		if(reset)
    		begin
    			mem_ir <= 16'b0000_0000_0000_0000;
    			reg_C <= 16'b0000_0000_0000_0000;
    			smdr1 <= 16'b0000_0000_0000_0000;
    			zf <= 1'b0;
    			nf <= 1'b0;
    			cf <= 1'b0;
    			dw <= 1'b0;
    		end
    		else if(state == `exec)
    		begin
    			mem_ir <= ex_ir;
    			reg_C <= ALUo;
    			cf <= cf_temp;
    			if((ex_ir[15:11] == `ADD)
    			 ||(ex_ir[15:11] == `CMP)
    			 ||(ex_ir[15:11] == `ADDI)
    			 ||(ex_ir[15:11] == `SUB)
    			 ||(ex_ir[15:11] == `SUBI)
    			 ||(ex_ir[15:11] == `LDIH)
    			 ||(ex_ir[15:11] == `SLL)
    			 ||(ex_ir[15:11] == `SRL)
    			 ||(ex_ir[15:11] == `SLA)
    			 ||(ex_ir[15:11] == `SRA)
    			 ||(ex_ir[15:11] == `ADDC)
    			 ||(ex_ir[15:11] == `SUBC))
    			begin
    				if(ALUo == 16'b0000_0000_0000_0000)
    					zf <= 1'b1;
    				else
    					zf <= 1'b0;
    				
    				if(ALUo[15] == 1'b1)
    					nf <= 1'b1;
    				else
    					nf <= 1'b0;
    			end
    			else if(ex_ir[15:11] == `STORE)
    			begin
    				dw <= 1'b1;
    				smdr1 <= smdr;
    			end
    		end
    		else
    		begin
    			reg_C <= reg_C;
    			smdr1 <= smdr1;
    			dw <= dw;
    		end
    	end
    	//ALU
    	reg cf_temp;
    	always@(*)
    	begin
    		if(state == `exec)
    		begin
    			if(reset)
    			begin
    				ALUo <= 16'b0000_0000_0000_0000;
    				cf_temp <= 0;
    			end
    			else
    				case(ex_ir[15:11])
    					`NOP:		{cf_temp, ALUo} <= {cf_temp, ALUo};
    					`HALT:	{cf_temp, ALUo} <= {cf_temp, ALUo};
    					`AND:		{cf_temp, ALUo} <= {cf_temp, reg_A & reg_B};
    					`OR:		{cf_temp, ALUo} <= {cf_temp, reg_A | reg_B};
    					`XOR:		{cf_temp, ALUo} <= {cf_temp, reg_A ^ reg_B};
    					`SLL:		{cf_temp, ALUo} <= {cf_temp, reg_A << reg_B};
    					`SRL:		{cf_temp, ALUo} <= {cf_temp, reg_A >> reg_B};
    					`SLA:		{cf_temp, ALUo} <= {cf_temp, reg_A <<< reg_B};
    					`SRA:		{cf_temp, ALUo} <= {cf_temp, reg_A >>> reg_B};
    					`JUMP:	{cf_temp, ALUo} <= {cf_temp, reg_B};
    					`LDIH:	{cf_temp, ALUo} <= {1'b0 + reg_A} + {1'b0 + reg_B};
    					`ADD:		{cf_temp, ALUo} <= {1'b0 + reg_A} + {1'b0 + reg_B};
    					`ADDI:	{cf_temp, ALUo} <= {1'b0 + reg_A} + {1'b0 + reg_B};
    					`ADDC:	{cf_temp, ALUo} <= {1'b0 + reg_A} + {1'b0 + reg_B} + cf;
    					`SUB:		{cf_temp, ALUo} <= {1'b0 + reg_A} - {1'b0 + reg_B};
    					`SUBI:	{cf_temp, ALUo} <= {1'b0 + reg_A} - {1'b0 + reg_B};
    					`SUBC:	{cf_temp, ALUo} <= {1'b0 + reg_A} - {1'b0 + reg_B} - cf;
    					`CMP:		{cf_temp, ALUo} <= {1'b0 + reg_A} - {1'b0 + reg_B};
    					`LOAD:	begin ALUo <= reg_A + reg_B; cf_temp <= cf_temp; end
    					`STORE:	begin ALUo <= reg_A + reg_B; cf_temp <= cf_temp; end
    					`JMPR:	begin ALUo <= reg_A + reg_B; cf_temp <= cf_temp; end
    					`BZ:		begin ALUo <= reg_A + reg_B; cf_temp <= cf_temp; end
    					`BNZ:		begin ALUo <= reg_A + reg_B; cf_temp <= cf_temp; end
    					`BN:		begin ALUo <= reg_A + reg_B; cf_temp <= cf_temp; end
    					`BNN:		begin ALUo <= reg_A + reg_B; cf_temp <= cf_temp; end
    					`BC:		begin ALUo <= reg_A + reg_B; cf_temp <= cf_temp; end
    					`BNC:		begin ALUo <= reg_A + reg_B; cf_temp <= cf_temp; end
    					default:	{cf_temp, ALUo} <= {cf_temp, ALUo};
    				endcase
    		end
    	end
    	/***************************************/
    	
    	/***************MEM*********************/
    	always@(posedge clock or posedge reset)
    	begin
    		if(reset)
    		begin
    			reg_C1 <= 16'b0000_0000_0000_0000;
    			wb_ir <= 16'b0000_0000_0000_0000;
    		end
    		else if(state == `exec)
    		begin
    			wb_ir <= mem_ir;
    			if(mem_ir[15:11] == `LOAD)
    				reg_C1 <= d_datain;
    			else
    				reg_C1 <= reg_C;
    		end
    	end
    	/***************************************/
    	
    	/****************WB********************/
    	always@(posedge clock or posedge reset)
    	begin
    		if(reset)
    		begin
    			gr[0] <= 16'b0000_0000_0000_0000;
    			gr[1] <= 16'b0000_0000_0000_0000;
    			gr[2] <= 16'b0000_0000_0000_0000;
    			gr[3] <= 16'b0000_0000_0000_0000;
    			gr[4] <= 16'b0000_0000_0000_0000;
    			gr[5] <= 16'b0000_0000_0000_0000;
    			gr[6] <= 16'b0000_0000_0000_0000;
    			gr[7] <= 16'b0000_0000_0000_0000;
    		end
    		else if(state == `exec)
    		begin
    			if((wb_ir[15:11] == `LOAD)
    			 ||(wb_ir[15:11] == `ADD)
    			 ||(wb_ir[15:11] == `ADDI)
    			 ||(wb_ir[15:11] == `ADDC)
    			 ||(wb_ir[15:11] == `SUB)
    			 ||(wb_ir[15:11] == `SUBI)
    			 ||(wb_ir[15:11] == `SUBC)
    			 ||(wb_ir[15:11] == `AND)
    			 ||(wb_ir[15:11] == `OR)
    			 ||(wb_ir[15:11] == `XOR)
    			 ||(wb_ir[15:11] == `SLL)
    			 ||(wb_ir[15:11] == `SRL)
    			 ||(wb_ir[15:11] == `SLA)
    			 ||(wb_ir[15:11] == `SRA)
    			 ||(wb_ir[15:11] == `LDIH))
    				gr[wb_ir[10:8]] <= reg_C1;
    		end
    		else
    		begin
    		
    		end
    	end
    	/***************************************/
    	
    	/**************select Y*****************/
    	always@(*)
    	begin
    		case(select_y)
    			4'b0000:	y <= reg_C;
    			4'b0001:	y <= reg_A;
    			4'b0010:	y <= reg_B;
    			4'b0011:	y <= {pc, 8'b0000_0000};
    			4'b0100:	y <= id_ir;
    			4'b0101:	y <= smdr;
    			4'b0110:	y <= reg_C1;
    			4'b0111:	y <= smdr1;
    			4'b1000:	y <= ex_ir;
    			4'b1001:	y <= mem_ir;
    			4'b1010:	y <= wb_ir;
    			default: y <= reg_C;
    		endcase
    	end
    	/***************************************/
    endmodule
    

    I_mem.v

    指令存储区域。把指令写在这一部分,即可让CPU跑指定的指令。

    `timescale 1ns / 1ps
    `include"headfile.v"
    
    module I_mem(
    	input mem_clk,
    	input [7:0] addr,
    	output wire [15:0] rdata
        );
    
    	reg [15:0] i_mem [255:0];
    	assign rdata = i_mem[addr];
    	
    	always@(posedge mem_clk)
    	begin
    		case(addr)
    			0:		i_mem[addr] <= {`ADDI, `gr1, 4'b1010, 4'b1011};
    			1:		i_mem[addr] <= {`LDIH, `gr2, 4'b0011, 4'b1100};
    			2:		i_mem[addr] <= {`ADD, `gr3, 1'b0, `gr1, 1'b0, `gr2};
    			3:		i_mem[addr] <= {`STORE, `gr3, 1'b0, `gr0, 4'b0000};
    			4:		i_mem[addr] <= {`ADDI, `gr1, 4'b0001, 4'b0001};
    			5:		i_mem[addr] <= {`LDIH, `gr2, 4'b0001, 4'b0001};
    			6:		i_mem[addr] <= {`ADD, `gr3, 1'b0, `gr1, 1'b0, `gr2};
    			7:		i_mem[addr] <= {`STORE, `gr3, 1'b0, `gr0, 4'b0001};
    			8:		i_mem[addr] <= {`LOAD, `gr1, 1'b0, `gr0, 4'b0000};
    			9:		i_mem[addr] <= {`LOAD, `gr2, 1'b0, `gr0, 4'b0001};
    			10:	i_mem[addr] <= {`ADD, `gr3, 1'b0, `gr1, 1'b0, `gr2};
    			11:	i_mem[addr] <= {`STORE, `gr3, 1'b0, `gr0, 4'b0001};
    			12:	i_mem[addr] <= {`JUMP, 4'b0000, 4'b0010, 4'b1000};
    			13:	i_mem[addr] <= {`ADDI, `gr1, 4'b1010, 4'b1011};
    			40:	i_mem[addr] <= {`HALT, 11'b000_0000_0000};
    			default:		i_mem[addr] <= {`NOP, 11'b000_0000_0000};
    		endcase
    	end
    
    endmodule
    

    D_mem.v

    数据存储区域。结构简单,根据dwe信号来决定是读取还是写入。

    `timescale 1ns / 1ps
    `include"headfile.v"
    
    module D_mem(
    	input mem_clk,
    	input dwe,
    	input [7:0] addr,
    	input [15:0] wdata,
    	output wire [15:0] rdata
        );
    	
    	reg [15:0] d_mem [255:0];
    	assign rdata = d_mem[addr];
    	
    	always@(posedge mem_clk)
    	begin
    			if(dwe)
    				d_mem[addr] <= wdata;
    	end
    
    
    endmodule
    

    light_show.v

    七段译码管显示模块。

    `timescale 1ns / 1ps
    
    module light_show(
    	input light_clk,
    	input reset,
    	input [15:0] y,
    	output reg [6:0] light,
    	output reg [3:0] en
        );
    
    	reg [1:0] dp;
    	reg [3:0] four;
    
    	always@(posedge light_clk or posedge reset)
    	begin
    		if(reset)
    			dp <= 0;
    		else
    		begin
    			dp <= dp + 1'b1;
    		end
    	end
    	
    	always@(*)
    	begin
    		if(reset)
    		begin
    			four <= 0;
    			en <= 0;
    		end
    		else
    		begin
    			case(dp)
    				0:			begin four <= y[3:0]; en <= 4'b1110; end
    				1:			begin four <= y[7:4]; en <= 4'b1101; end
    				2:			begin four <= y[11:8]; en <= 4'b1011; end
    				3:			begin four <= y[15:12]; en <= 4'b0111; end
    				default:	begin four <= 0; en <= 0; end
    			endcase
    		end
    	end
    	
    	always@(*)
    	begin
    		if(reset)
    		begin
    			light <= 7'b0001000;
    		end
    		else
    		begin
    			case(four)
    				0:				light <= 7'b0000001;
    				1:				light <= 7'b1001111;
    				2:				light <= 7'b0010010;
    				3:				light <= 7'b0000110;
    				4:				light <= 7'b1001100;
    				5:				light <= 7'b0100100;
    				6:				light <= 7'b0100000;
    				7:				light <= 7'b0001111;
    				8:				light <= 7'b0000000;
    				9:				light <= 7'b0000100;
    				4'b1010:		light <= 7'b0001000;
    				4'b1011:		light <= 7'b1100000;
    				4'b1100:		light <= 7'b0110001;
    				4'b1101:		light <= 7'b1000010;
    				4'b1110:		light <= 7'b0110000;
    				4'b1111:		light <= 7'b0111000;
    				default:		light <= 7'b0000001;
    			endcase
    		end
    	end
    
    endmodule
    

    VTF_CPU.v

    仿真测试文件。

    `timescale 1ns / 1ps
    
    module VTF_CPU;
    
    	// Inputs
    	reg clk;
    	reg enable;
    	reg reset;
    	reg [3:0] SW;
    	reg start;
    	reg button;
    
    	// Outputs
    	wire [6:0] light;
    	wire [3:0] en;
    
    	// Instantiate the Unit Under Test (UUT)
    	CPU uut (
    		.clk(clk), 
    		.enable(enable), 
    		.reset(reset), 
    		.SW(SW), 
    		.start(start), 
    		.button(button), 
    		.light(light), 
    		.en(en)
    	);
    
    	initial begin
    		// Initialize Inputs
    		clk = 0;
    		enable = 0;
    		reset = 0;
    		SW = 0;
    		start = 0;
    		button = 0;
    
    		// Wait 100 ns for global reset to finish
    		#100;
    		
    		$display("pc:     id_ir      :reg_A:reg_B:reg_C:da:dd:  :w:reC1:gr1 :gr2 : gr3");
    		$monitor("%h:%b:%h:%h:%h:%h:%h:%b:%h:%h:%h:%h", 
    			uut.pcpu.pc, uut.pcpu.id_ir, uut.pcpu.reg_A, uut.pcpu.reg_B, uut.pcpu.reg_C,
    			uut.d_addr, uut.d_dataout, uut.d_we, uut.pcpu.reg_C1, uut.pcpu.gr[1], uut.pcpu.gr[2], uut.pcpu.gr[3]);
    			
          enable <= 0; start <= 0;
    		// Add stimulus here
    		#10 reset <= 1;
    		#10 reset <= 0;
    		#10 enable <= 1;
    		#10 start <=1;
    		//#10 start <= 0;
    		#100;
    	end
       always #20 button = ~button;
    	always #5 clk = ~clk;
    endmodule
    
    
  • 相关阅读:
    asp.net core MVC 入门学习
    C# 中关于重载与重写的区别及用法
    C# 生成随机的6位字母,包含大小写
    C# CheckBoxList绑定值,设置及获取
    jquery中checkbox的全选与反选
    docker 执行 docker system prune 导致Azure Devops build镜像失败
    Navicat 连接mysql 报错: Authentication plugin caching_ sha2_password cannot be loaded
    docker build 错误 /usr/share/dotnet/sdk/2.1.801/Microsoft.Common.CurrentVersion.targets(2106,5): warning MSB3245: Could not resolve this reference
    Azure Devops: COPY failed: stat /var/lib/docker/tmp/docker-builder268095359/xxxxxxx.csproj no such file or directory
    Azure DevOps vsts-agent-linux 安装出错, Must not run with sudo
  • 原文地址:https://www.cnblogs.com/wsine/p/4292869.html
Copyright © 2011-2022 走看看