简单周期CPU的Verliog代码的实现和通过在proteus上进行C51仿真LED流水灯实验

简单周期CPU的Verliog代码的实现和通过在proteus上进行C51仿真LED流水灯实验

@[toc](目录)

一.简单周期CPU的Verliog代码的实现

1.概述

本文所设计的单周期CPU的指令系统采用类似MIPS的设计风格,包括以下四类指令:

(1) 运算类指令;

(2) 传送类指令;

(3) 存储类指令;

(4) 控制类指令;

其中,所有指令的操作码部分用4位二进制表示,寄存器编号用3位二进制表示。在下述的具体设计表示中,以助记符表示的是汇编指令;以代码表示的则是二进制机器指令。

2.整体框架设计

本文所设计的单周期CPU的整体框架主要包括七部分:程序计数器、指令寄存器、寄存器组、算术逻辑单元、数据存储器、控制单元和顶层模块。具体框架如下:
在这里插入图片描述

3.具体实现

程序计数器

代码如下:

module PC(    
    input clk,    
    input [15:0] PCin,    
    input PCWre,    
    input Reset,    
    output reg [15:0] PCout    
);    
      
    initial begin    
        PCout <= 0;   
    end  
        
    always@(posedge clk) begin    
        if(Reset == 0) begin    
            PCout <= 0;    
        end    
        else if(PCWre == 0) begin    
            PCout <= PCout;    
        end    
        else begin    
            PCout <= PCin;    
        end    
    end  
        
endmodule   
指令存储器

代码如下:

module InsMemory(    
    input InsMemRW,    
    input [15:0] address,    
    output reg [15:0] DataOut    
);    
 
    reg [7:0] mem [0:127];   
 
    initial begin    
        DataOut = 16'b1111000000000000;  
        $readmemb("Instructions.txt", mem);      
    end   
      
    always@(*) begin   
        DataOut[15:8] <= mem[address];    
        DataOut[7:0] <= mem[address+1];  
    end   
       
endmodule
寄存器组

代码如下:

module RegFile(    
    input CLK,    
    input RST,    
    input RegWre,    
    input [2:0] ReadReg1,    
    input [2:0] ReadReg2,    
    input [2:0] WriteReg,    
    input [15:0] WriteData,    
    output [15:0] ReadData1,    
    output [15:0] ReadData2    
);    
  
    reg [15:0] regFile[0:7];  
       
    integer i;    
      
    assign ReadData1 = regFile[ReadReg1];   
    assign ReadData2 = regFile[ReadReg2];  
        
    always @ (negedge CLK) begin    
        if (RST == 0) begin    
            for(i=1;i<8;i=i+1)    
                regFile[i] <= 0;    
        end    
        else if(RegWre == 1 && WriteReg != 0) begin    
            regFile[WriteReg] <= WriteData;    
        end    
    end    
            
endmodule   
算数逻辑单元

代码如下:

module ALU(    
    input [2:0] ALUopcode,    
    input [15:0] rega,    
    input [15:0] regb,    
    output reg [15:0] result,    
    output zero,    
    output sign    
);    
  
    assign zero = (result==0)?1:0;    
    assign sign = result[15];    
      
    always @( ALUopcode or rega or regb ) begin    
        case (ALUopcode)    
            3'b000 : result = rega + regb;    
            3'b001 : result = rega - regb;    
            3'b010 : result = regb << rega;    
            3'b011 : result = rega | regb;    
            3'b100 : result = rega & regb;    
            3'b101 : result = (rega < regb)?1:0;     
            3'b110 : begin    
                if (rega<regb &&(( rega[15] == 0 && regb[15]==0) ||    
                (rega[15] == 1 && regb[15]==1))) result = 1;    
                else if (rega[15] == 0 && regb[15]==1) result = 0;    
                else if ( rega[15] == 1 && regb[15]==0) result = 1;    
                else result = 0;    
            end    
            3'b111 : result = regb;    
        endcase    
    end   
       
endmodule   
数据存储器

代码如下:

module DataMemory(    
    input clk,    
    input [15:0] address,    
    input RD,    
    input WR,    
    input [15:0] DataIn,    
    output [15:0] DataOut    
);    
    
    reg [7:0] ram[0:127];  
        
    integer i;    
      
    initial begin;    
        for(i=0;i<128;i=i+1)    
            ram[i]<=0;    
    end    
       
    assign DataOut[7:0] = (RD == 0)? ram[address+1]:8'bz;    
    assign DataOut[15:8] = (RD == 0)? ram[address]:8'bz;    
   
    always@(negedge clk) begin    
        if(WR == 0) begin    
            if(address>=0 && address<128) begin    
                ram[address] <= DataIn[15:8];    
                ram[address+1] <= DataIn[7:0];     
            end    
        end    
    end  
        
endmodule 
控制单元

代码如下:

module ControlUnit(    
    input [3:0] opcode,    
    input zero,    
    input sign,    
    output reg PCWre,    
    output reg ALUSrcA,    
    output reg ALUSrcB,    
    output reg DBDataSrc,    
    output reg RegWre,    
    output reg InsMemRW,    
    output reg RD,    
    output reg WR,    
    output reg RegDst,    
    output reg ExtSel,    
    output reg [1:0] PCSrc,    
    output reg [2:0] ALUOp    
);    
  
    initial begin    
        RD = 1;    
        WR = 1;    
        RegWre = 0;   
        PCWre = 0;   
        InsMemRW = 1;    
    end   
       
    always@ (opcode) begin    
        case(opcode)     
            4'b0000:begin // add    
                PCWre = 1;    
                ALUSrcA = 0;    
                ALUSrcB = 0;    
                DBDataSrc = 0;    
                RegWre = 1;    
                InsMemRW = 1;    
                RD = 1;    
                WR = 1;    
                RegDst = 1;    
                ALUOp = 3'b000;    
            end    
            4'b0001:begin //addi    
                PCWre = 1;    
                ALUSrcA = 0;    
                ALUSrcB = 1;    
                DBDataSrc = 0;    
                RegWre = 1;    
                InsMemRW = 1;    
                RD = 1;    
                WR = 1;    
                RegDst = 0;    
                ExtSel = 1;    
                ALUOp = 3'b000;    
            end    
            4'b0010:begin //sub    
                PCWre = 1;    
                ALUSrcA = 0;    
                ALUSrcB = 0;    
                DBDataSrc = 0;    
                RegWre = 1;    
                InsMemRW = 1;    
                RD = 1;    
                WR = 1;    
                RegDst = 1;    
                ALUOp = 3'b001;    
            end  
            4'b0011:begin // or    
                PCWre = 1;    
                ALUSrcA = 0;    
                ALUSrcB = 0;    
                DBDataSrc = 0;    
                RegWre = 1;    
                InsMemRW = 1;    
                RD = 1;    
                WR = 1;    
                RegDst = 1;    
                ALUOp = 3'b011;    
            end     
            4'b0100:begin // ori    
                PCWre = 1;    
                ALUSrcA = 0;    
                ALUSrcB = 1;    
                DBDataSrc = 0;    
                RegWre = 1;    
                InsMemRW = 1;    
                RD = 1;    
                WR = 1;    
                RegDst = 0;    
                ExtSel = 0;    
                ALUOp = 3'b011;    
            end    
            4'b0101:begin //and    
                PCWre = 1;    
                ALUSrcA = 0;    
                ALUSrcB = 0;    
                DBDataSrc = 0;    
                RegWre = 1;    
                InsMemRW = 1;    
                RD = 1;    
                WR = 1;    
                RegDst = 1;    
                ALUOp = 3'b100;    
            end    
            4'b0110:begin //sll    
                PCWre = 1;    
                ALUSrcA = 1;    
                ALUSrcB = 0;    
                DBDataSrc = 0;    
                RegWre = 1;    
                InsMemRW = 1;    
                RD = 1;    
                WR = 1;    
                RegDst = 1;    
                ALUOp = 3'b010;    
            end    
            4'b0111:begin //slt    
                PCWre = 1;    
                ALUSrcA = 0;    
                ALUSrcB = 0;    
                DBDataSrc = 0;    
                RegWre = 1;    
                InsMemRW = 1;    
                RD = 1;    
                WR = 1;    
                RegDst = 1;    
                ALUOp = 3'b110;    
            end  
            4'b1000:begin //mov    
                PCWre = 1;    
                ALUSrcA = 0;    
                ALUSrcB = 0;    
                DBDataSrc = 0;    
                RegWre = 1;    
                InsMemRW = 1;    
                RD = 1;    
                WR = 1;    
                RegDst = 1;    
                ExtSel = 1;    
                ALUOp = 3'b111;    
            end  
            4'b1001:begin //movi    
                PCWre = 1;    
                ALUSrcA = 0;    
                ALUSrcB = 1;    
                DBDataSrc = 0;    
                RegWre = 1;    
                InsMemRW = 1;    
                RD = 1;    
                WR = 1;    
                RegDst = 0;    
                ExtSel = 1;    
                ALUOp = 3'b111;    
            end      
            4'b1010:begin //sw    
                PCWre = 1;    
                ALUSrcA = 0;    
                ALUSrcB = 1;    
                RegWre = 0;    
                InsMemRW = 1;    
                RD = 1;    
                WR = 0;    
                ExtSel =1;    
                ALUOp = 3'b000;    
            end    
            4'b1011:begin //lw    
                PCWre = 1;    
                ALUSrcA = 0;    
                ALUSrcB = 1;    
                DBDataSrc = 1;    
                RegWre = 1;    
                InsMemRW = 1;    
                RD = 0;    
                WR = 1;    
                RegDst = 0;    
                ExtSel = 1;    
                ALUOp = 3'b000;    
            end   
            4'b1100:begin //beq    
                PCWre = 1;    
                ALUSrcA = 0;    
                ALUSrcB = 0;    
                RegWre = 0;    
                InsMemRW = 1;    
                RD = 1;    
                WR = 1;    
                ExtSel = 1;    
                ALUOp = 3'b001;    
            end    
            4'b1101:begin  //bgtz  
                PCWre = 1;    
                ALUSrcA = 0;    
                ALUSrcB = 0;    
                RegWre = 0;    
                InsMemRW = 1;    
                RD = 1;    
                WR = 1;    
                ExtSel = 1;    
                ALUOp = 3'b001;    
            end    
            4'b1110:begin //j    
                PCWre = 1;    
                RegWre = 0;    
                InsMemRW = 1;    
                RD = 1;    
                WR = 1;    
                ALUOp = 3'b010;    
            end    
            4'b1111:begin //halt    
                PCWre = 0;    
                RegWre = 0;    
                InsMemRW = 1;    
                RD = 1;    
                WR = 1;    
            end    
            default:begin    
                RD = 1;    
                WR = 1;    
                RegWre = 0;    
                InsMemRW = 0;    
            end    
        endcase    
    end   
       
    always@(opcode or zero or sign) begin    
        if(opcode == 4'b1110) // j    
            PCSrc = 2'b10;    
        else if(opcode == 4'b1100) begin  
            if(zero == 1)  
                PCSrc = 2'b01;  
            else  
                PCSrc = 2'b00;  
        end  
        else if(opcode == 4'b1101) begin  
            if(zero == 0 && sign == 0)    
                PCSrc = 2'b01;    
            else    
                PCSrc = 2'b00;  
        end    
        else begin    
            PCSrc = 2'b00;    
        end    
    end   
       
endmodule    

顶层模块实现

在这里插入图片描述

二.通过在proteus上进行C51仿真LED流水灯实验

1.建立项目

在完成安装后,进行项目的配置,配置时需注意一定要使用AT89C51作为芯片。

在这里插入图片描述

2.进行线路连接

1)首先进入原理图绘制界面,进行原理图设计,
先点击上方的原理图设计,在点击P,在界面中搜索AT89C51,找到其芯片,并按照相同的方式,找到LED-YELLOW(流水灯)和RES(电阻)。

在这里插入图片描述

  1. 再将芯片和8个流水灯放入设计界面,

    在这里插入图片描述

3)再放入8个电阻并将其连线,

在这里插入图片描述

4)依次为他们编号并将电阻的值改为300,让流水灯更亮,

在这里插入图片描述

5)最后加入电源,并将名称改为VCC,

在这里插入图片描述

二.完成程序的编写

1.创建项目

在新建项目时,一定要选择AT89C51芯片,

在这里插入图片描述

2.进行程序编写

1)主要程序如下:

//51单片机编程常用的头文件
	#include <reg51.h>
	#include <intrins.h>
	//延迟函数
	void delay_ms(int a)
	{
		int i,j;
		for(i=0;i<a;i++)
		{
			for(j=0;j<1000;j++) _nop_();
	
		}
	}
	
	void main(void)
	{
		while(1)
		{
			P0=0xfe;
			delay_ms(50);
			P0=0xfd;
			delay_ms(50);
			P0=0xfb;
			delay_ms(50);
			P0=0xf7;
			delay_ms(50);
			P0=0xef;
			delay_ms(50);
			P0=0xdf;
			delay_ms(50);
			P0=0xbf;
			delay_ms(50);
			P0=0x7f;
			delay_ms(50);
		}
	}

2)点击保存,并在命名的同时加上.c的后缀来表明这是一个c程序,

3)再右键点击Source Group1 并选择将这个文件添加到Source Group1,

在这里插入图片描述

4)再选择刚刚保存的文件,然后点击添加,

5)点击上方的options for target按钮,点击窗口里的output,选上 create hex file ,

在这里插入图片描述

6)最后进行编译,

在这里插入图片描述

三.开始进行仿真

1)双击AT89C51芯片,在program file处查找到刚才创造的hex文件,

在这里插入图片描述

2)点击运行,

在这里插入图片描述

四.总结

这次对于AT89C51芯片流水灯的仿真实验,让我对开发的大概流程和大致原理有了一定的了解,为接下来的学习打下了基础。

  • 21
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值