Verilog 简易单周期CPU

news2024/11/24 1:30:16

目录

 本实验包含:

 简易结构图:

各部件代码或实现:

控制器:

寄存器堆:

ALU:

数据存储器:

指令存储器:

CPU:

tp(仿真文件):

 仿真结果:

 单周期CPU压缩包下载


 本实验包含:

        指令存储器和数据存储器的ip核调用,控制器,寄存器堆,ALU,单周期CPU的实现。

 简易结构图:

各部件代码或实现:

控制器:

控制器有13条指令,需要可以再加,照着之前格式注释加就行了,对于同RAM相关的指令未测试

R:
 指令  [31:26]   [25:21]   [20:16]  [15:11] [10:6]  [5:0] 功能
add000000rsrtrd000000100000寄存器加
sub000000rsrtrd000000100010寄存器减
and000000rsrtrd000000100100寄存器与
or000000rsrtrd000000100101寄存器或
nor000000rsrtrd000000100111寄存器或非
sll000000rs000000rdsa000000逻辑左移
srl000000rs000000rdsa000010 逻辑右移
sra000000rs000000rdsa100111算术右移
I:
指令 [31:26] [25:21] [20:16] [15:0] 功能
addi001000rsrtimmediate立即数加
lw100011rsrtimmediate取字数据
sw101011rsrtimmediate存字数据
beq000100rsrtimmediate相等转移
J:
指令[31:26][25:21][20:16][15;0]功能
j0000100000000000immediate转移

输入:op,func
输出:MemtoReg,MemWrite,Branch,ALUOP,ALUSrc,RegWrite,RegDst

//
//创建日期:2022/12/19 10:46:36
//设计名称:控制器
//课程名称:Controler
//说明: 
//输入:op,func
//输出:MemtoReg,MemWrite,Branch,ALUOP,ALUSrc,RegWrite,RegDst
//依赖项:
//      
//版次:
//版本0.01-文件已创建
//其他注释:
//
//
module Controler(op,func,MemtoReg,MemWrite,Branch,ALUOP,ALUSrc,RegWrite,RegDst);
    input [5:0] op;
    input [5:0] func;
    output MemtoReg;
    output MemWrite;
    output Branch;
    output [11:0] ALUOP;
    output ALUSrc;
    output RegWrite;
    output RegDst;
    reg MemtoReg,MemWrite,Branch,ALUSrc,RegWrite,RegDst;
    reg [11:0] ALUOP;
    //    R:
    //    指令	[31:26]	[25:21]	[20:16]	[15:11]	[10:6]	[5:0]	功能
    //    add	000000	   rs	 rt	       rd	000000	100000	寄存器加
    //    sub	000000	   rs	 rt	       rd	000000	100010	寄存器减
    //    and	000000	   rs	 rt	       rd	000000	100100	寄存器与
    //    or	000000	   rs	 rt	       rd	000000	100101	寄存器或
    //    nor	000000	   rs	 rt	       rd	000000	100111	寄存器或非
    //    sll	000000	   rs  000000	   rd	  sa	000000	逻辑左移
    //    srl	000000	   rs  000000	   rd	  sa	000010	逻辑右移
    //    sra	000000	   rs  000000	   rd	  sa	000011	算术右移
    //I:
    //    指令	[31:26]	[25:21]	[20:16]	[15:0]	功能
    //    addi	001000	  rs	rt    immediate	立即数加
    //    lw	100011	  rs	rt	  immediate	取字数据
    //    sw	101011	  rs	rt	  immediate	存字数据
    //    beq	000100	  rs	rt	  immediate	相等转移
    //J:
    //    指令	[31:26] [25:21] [20:16]  [15:0]     功能
    //    j 	000010	00000	00000	 immediate	转移

    always @(*)
    begin
        case(op)
            6'b000000://寄存器操作
            begin
                MemtoReg=0;//输出ALU的输出
                MemWrite=0;//数据存储器不写入
                Branch=0;//正常PC
                ALUSrc=0;//ALU输入2选择寄存器输出
                RegWrite=1;//寄存器写入
                RegDst=1;//有rd
                case(func)  //控制ALU操作
                    6'b100000:// 寄存器加
                        ALUOP=12'b010000000000;
                    6'b100010:// 寄存器减
                        ALUOP=12'b100000000000;
                    6'b100100:// 寄存器与
                        ALUOP=12'b000010000000;
                    6'b100101:// 寄存器或
                        ALUOP=12'b000000100000;
                    6'b100111:// 寄存器或非
                        ALUOP=12'b000001000000;
                    6'b100100:// 逻辑左移
                        ALUOP=12'b000000001000;
                    6'b100101:// 逻辑右移
                        ALUOP=12'b000000000100;
                    6'b100111:// 算术右移
                        ALUOP=12'b000000000010;
                    default:ALUOP=12'b010000000000;
                endcase
            end
            6'b001000:// 立即数加
            begin
                MemtoReg=0;//输出ALU结果
                MemWrite=0;//数据存储器不写入
                Branch=0;//正常PC
                ALUOP=12'b010000000000;//ALU加操作
                ALUSrc=1;//数据2选择立即数输出
                RegWrite=1;//寄存器写入
                RegDst=0;//无rd选择rt
            end
            6'b100011:// 取字数据
            begin
                MemtoReg=1;//输出数据存储器结果
                MemWrite=0;//数据存储器不写入
                Branch=0;//正常PC
                ALUOP=12'b000000000000;//ALU无操作,输出第一个输入
                ALUSrc=1;//数据2随意
                RegWrite=1;//寄存器写入
                RegDst=0;//无rd选择rt
            end
            6'b101011:// 存字数据
            begin
                MemtoReg=1;//输出随意
                MemWrite=1;//数据存储器写入
                Branch=0;//正常PC
                ALUOP=12'b000000000000;//ALU无操作,输出第一个输入
                ALUSrc=1;//数据2随意
                RegWrite=0;//寄存器不写入
                RegDst=0;//不写入随意
            end
            6'b000100:// 相等转移
            begin
                MemtoReg=1;//输出随意
                MemWrite=0;//数据存储器不写入
                Branch=1;//PC可能改变
                ALUOP=12'b000000000000;//ALU无操作,输出第一个输入
                ALUSrc=0;//ALU输入2选择寄存器输出
                RegWrite=0;//寄存器不写入
                RegDst=0;//不写入随意
            end
            6'b000010://跳转
            begin
                MemtoReg=1;//输出随意
                MemWrite=0;//数据存储器不写入
                Branch=1;//PC可能改变
                ALUOP=12'b000000000000;//ALU无操作,输出第一个输入
                ALUSrc=0;//数据2选择寄存器输出
                RegWrite=0;//寄存器不写入
                RegDst=0;//不写入随意
            end
            default:
            begin
                MemtoReg=0;
                MemWrite=0;
                Branch=0;
                ALUOP = 12'b000000000000;//ALU无操作,输出第一个输入
                ALUSrc=0;
                RegWrite=1;
                RegDst=1;
            end
        endcase
    end
endmodule

寄存器堆:

采用之前的寄存器堆(短版)代码,没有初始化,不影响使用,需要的话加上就行

//
//
//创建日期:2022/10/16 21:37:00
//设计名称:寄存器堆
//课程名称:regfile
//说明:
// 实现 32 个寄存器, 其中 0 号寄存器读出的值恒为 0,
// 寄存器堆为异步读同步写, 
// 共有 1 个写端口和 2 个读端口
//依赖项:
//      
//版次:
//版本0.01-文件已创建
//其他注释:
//
 
module regfile(
input clk,  // 时钟
input wen,  // 写使能
input [4 :0] raddr1,    // 读地址1
input [4 :0] raddr2,    // 读地址2
input [4 :0] waddr,     // 写地址
input [31:0] wdata,     // 写数据
output reg [31:0] rdata1,   // 读到的数据1
output reg [31:0] rdata2,   // 读到的数据2
input [4 :0] test_addr,     // 测试读端口
output reg [31:0] test_data // 测试输出
); 
reg [31:0] rf[31:0];  // 定义32个32位的寄存器
always @(posedge clk) // 时钟上升沿
begin
    if (wen)    // 如果写使能wen为1则写入寄存器
        begin
           rf[waddr] <= wdata;
        end
end
 
//读端口 1
always @(*)
begin
    if (raddr1==5'd0)
        rdata1 <= 32'd0;
    else
        rdata1 <= rf[raddr1];
end
//读端口 2
always @(*)
begin
    if (raddr2==5'd0)
        rdata2 <= 32'd0;
    else
        rdata2 <= rf[raddr2];
end
//测试读端口
always @(*)
begin
    if (test_addr==5'd0)
        test_data <= 32'd0;
    else
        test_data <= rf[test_addr];
end
endmodule

ALU:

对照之前的ALU增加了比较相等的输出,用于PC的跳转,采用独热编码,相当于13种简易运算。

//
//创建日期:2022/11/6 20:06:00
//设计名称:ALU算术逻辑单元
//课程名称:alu
//说明: 
//输入:   [11:0] alu_control;  // ALU控制信号
//        [31:0] alu_src1;     // ALU操作数1
//        [31:0] alu_src2;     // ALU操作数2
//输出:   [31:0] alu_result;   // ALU结果
//          Equal  两个输入是否相等
//依赖项:
//      
//版次:
//版本0.01-文件已创建
//其他注释:
//
//
module alu(alu_control,alu_src1,alu_src2,alu_result,Equal);
    input  [11:0] alu_control;  // ALU控制信号
    input  [31:0] alu_src1;     // ALU操作数1
    input  [31:0] alu_src2;     // ALU操作数2
    output [31:0] alu_result;   // ALU结果
    output Equal;   //相等
    wire Equal;
    reg [31:0] alu_result;
    // 控制信号为独热编码
    assign Equal = alu_src1==alu_src2;
    always @(*)
    begin
        case(alu_control)   // 下面的1,2指操作数1,操作数2
            12'b000000000001:alu_result<=alu_src1<<16;         // 高位加载       1
            12'b000000000010:alu_result<=alu_src1>>>alu_src2;         // 算术右移       2
            12'b000000000100:alu_result<=alu_src1>>alu_src2; // 逻辑右移      4
            12'b000000001000:alu_result<=alu_src1<<alu_src2; // 逻辑左移      8
            12'b000000010000:alu_result<=alu_src1^alu_src2; // 按位异或    16
            12'b000000100000:alu_result<=alu_src1|alu_src2;// 按位或    32
            12'b000001000000:alu_result<=~(alu_src1|alu_src2); // 按位或非       64
            12'b000010000000:alu_result<=alu_src1&alu_src2; // 按位与       128
            12'b000100000000:alu_result<=alu_src1<alu_src2?32'd1:32'd0;// 无符号比较,小于置位  256
            12'b001000000000:alu_result<=$signed(alu_src1)<$signed(alu_src2)?32'd1:32'd0;// 有符号比较,小于置位  512
            12'b010000000000:alu_result<=alu_src1+alu_src2;// 1加     1024
            12'b100000000000:alu_result<=alu_src1-alu_src2;// 1减     2048
            default: alu_result<=alu_src1;
        endcase
    end
endmodule

数据存储器:

采用IP核实现:

没有测试,功能或许有问题

         

 

指令存储器:

采用IP核实现:

 

 

 

 第四张图的ROM.coe数据如下:

memory_initialization_radix=2;
memory_initialization_vector=
00100000000000010000000000001000
00100000000000100000000000000010
00100000000000110000000000000000
00000000010000110001100000100000
00010000001000110000000000000111
00001000000000000000000000000011

这是一段测试用的指令段,具体功能在tp文件种有注释

这个文件什么名字和位置都可以,后缀是.coe就行。

CPU:

//
//创建日期:2022/12/19 16:32:56
//设计名称:CPU
//课程名称:CPU
//说明: 
//调用各个部件,进行运算
//依赖项:
//      控制器,寄存器,ALU
//版次:
//版本0.01-文件已创建
//其他注释:

module CPU(clk);
    input clk;
    // PC
    reg [7:0] PC=8'd0;//PC从第0条指令开始
    wire[31:0] SignImm;//指令后16位扩展结果
    wire PCSrc;//是否跳转
    always@(posedge clk)//上升沿
    begin
        if (PCSrc == 0)
            PC = PC+1;
        else
            PC = SignImm[7:0];
	end
    // 指令存储器
    wire [31:0] instructions;//指令存储器输出
    ROM_D IROM(
        .a(PC),//地址
        .spo(instructions));//指令输出
    wire[5:0] op,func;//控制器输入
    wire[4:0] rs,rt,rd;//三个寄存器地址
    assign op = instructions[31:26];
    assign func = instructions[5:0];
    assign rs = instructions[25:21];
    assign rt = instructions[20:16];
    assign rd = instructions[15:11];
    assign SignImm = {{(16){instructions[15]}},instructions[15:0]};
    // 控制器
    wire MemtoReg,MemWrite,Branch,ALUSrc,RegWrite,RegDst;//控制器输出控制信号
    wire[11:0] ALUOP;//ALU所做的操作
    Controler Contr(op,func,MemtoReg,MemWrite,Branch,ALUOP,ALUSrc,RegWrite,RegDst);
    // 寄存器堆
    wire[31:0] R1,R2,WriteBackData;//寄存器输出和数据输入
    wire[4:0] reg_w;//寄存器写地址
    assign reg_w = RegDst?rd:rt;
    regfile regfile_(clk,RegWrite,rs,rt,reg_w,WriteBackData,R1,R2);
    // ALU
    wire[31:0] srcB,ALUResult;//ALU第二个数据输入和数据输出
    wire Equal;//输入是否相等
    assign srcB = ALUSrc?SignImm:R2;
    alu ALU(ALUOP,R1,srcB,ALUResult,Equal);
    assign PCSrc = Branch&Equal;
    // 数据存储器
    wire [31:0] ReadData;//数据存储器输出
    data_RAM DRM(
        .clka  (clk          ),
        .wea   (MemWrite      ),
        .addra (ALUResult[7:0]),
        .dina  (R2            ),
        .douta (ReadData      ));
    assign WriteBackData = MemWrite?ReadData:ALUResult;
endmodule

tp(仿真文件):

就一个clk和CPU的调用,所用指令段的注释。

`timescale 1ns / 1ps

//001000 00000 00001 0000000000001000       第0个寄存器和8相加存入第1个寄存器
//001000 00000 00010 0000000000000010       第0个寄存器和2相加存入第2个寄存器
//001000 00000 00011 0000000000000000       第0个寄存器和0相加存入第3个寄存器
//000000 00010 00011 00011 00000 100000     第3个寄存器和第2个寄存器相加,结果存入第3个寄存器
//000100 00001 00011 0000000000000111       第1个寄存器和第3个相等转移到7
//000010 00000 00000 0000000000000011       转移到3
//相当于以下程序:
// reg[1] = 8
// reg[2] = 2
// reg[3] = 0
//M: reg[3] = reg[3]+reg[2]
// if reg[1] == reg[3]: goto N
// goto M
//N:
module tp;
    reg clk=0;
    CPU cpu_(clk);
    always #10 clk = ~clk;
endmodule

 仿真结果:

 

 

 

 

 单周期CPU压缩包下载

开了动态调分,初始积分是0.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/102594.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何去掉idea的诸多警告

File->setting->Editor->inspections 选择漏斗&#xff0c;选中warning&#xff0c;筛选出所有警告级别&#xff0c;然后去掉勾选&#xff0c;然后重启idea即可

重构物理Entity架构,支持更多的形状

上一节实战如何编译BEPUphysicsint源码到自己的项目, 如何整合物理引擎与Unity图形渲染。本节来从新调整设计,让物理的Entity基本操作与物理的形状分离,支持更多的物理形状,支持物理entity与Unity物体位移与旋转同步。主要分成以下3个部分: 1: 设计PhyBaseEntity&#xff0c;让…

学到一招!PyCharm连接MySQL竟如此简单!

在 PyCharm 中是可以通过内置的工具来连接、操作数据库的&#xff0c;并且对于市面上大多数主流数据库都是支持的。 连接 MySQL 首先打开 PyCharm &#xff0c;点击菜单栏的 View --> Tool Windows --> Database 或者直接点击 PyCharm 右侧的 Database 然后就会在 PyCh…

【QT开发笔记-基础篇】| 第五章 绘图QPainter | 5.6 矩形、圆角矩形

本节对应的视频讲解&#xff1a;B_站_视_频 https://www.bilibili.com/video/BV1mg411J7u5 本节讲解如何绘制矩形、圆角矩形 1. 相关的 API 直接查看官方的帮助文档&#xff0c;可以看到有多个重载的方法用于绘制矩形、圆角矩形 1.1 矩形 // 带 F 表示参数为浮点数&#x…

【电商】电商系统---合同管理

说一下合同管理部分&#xff0c;希望对大家有帮助&#xff0c;如果大家觉得简单可以直接略过&#xff0c;谢谢&#xff01; 合同分类 合同主要分为采购类合同、销售类合同、其他合同。 采购合同和销售合同分别与采购订单和销售订单建立对应关系&#xff0c;通过采购订单和销售…

ChatGDP:人类未来世界的主宰

先简单介绍一下今天的主角——ChatGPT。 ChatGPT是一款由OpenAI开发的聊天机器人&#xff0c;它具有出色的自然语言处理能力&#xff0c;能够与人类进行真实的对话。它的核心技术是GPT-3语言模型&#xff0c;能够自动学习语言特征&#xff0c;并进行语义理解、文本生成等任务。…

HCL与Pipe、Autoit和MobaXterm的组合使用

我们平时做实验一般会用到真机或者是模拟器&#xff0c;因为我主要接触的都是一些H3C的产品和技术&#xff0c;所以模拟器用HCL会多一些。为了呈现出相对好一些的视觉效果&#xff0c;我一般会使用MobaXterm工具进行命令操作&#xff0c;所以大家看到的回显一般是这样的&#x…

哈工大视听觉信号处理——听觉部分报告——一种智能家居命令词识别系统的设计

题 目 听觉部分 专 业 软件工程 学   号 120L0219XX 班   级 2037101 姓 名 李启明 报 告 日 期 2022.12.20 一、基频 &#xff08;一&#xff…

肝了一周总结的SpringBoot常用注解大全,一目了然~

平时使用SpringBoot开发项目&#xff0c;少不了要使用到它的注解。这些注解让我们摆脱了繁琐的传统Spring XML配置&#xff0c;让我们开发项目更加高效&#xff0c;今天我们就来聊聊SpringBoot中常用的注解&#xff01; SpringBoot实战电商项目mall&#xff08;50kstar&#xf…

《c专家编程》读书笔记

《c专家编程》第一章 C&#xff1a;穿越时空的迷雾第二章 这不是Bug&#xff0c;而是语言特性gets实验第三章 分析C语言的声明const实验第四章 令人震惊的事实&#xff1a;数组和指针并不相同指针与数组实验第五章 对链接的思考简单静态库动态库实验第六章 运动的诗章&#xff…

python-(6-5-3)爬虫---修改代码

文章目录一 事件背景二 系统给的代码三 改进措施四 改进后的代码一 事件背景 本篇主要是生活分享。 公司研究了一个比较好玩的人工智能狗&#xff0c;我就想偷懒让它帮我写个代码&#xff0c;得到的漂亮小姐姐的照片&#xff0c;然后它还真的给我把代码弄出来了。 二 系统给的…

​九州一轨通过注册:计划募资6.57亿 京投公司为大股东

雷递网 雷建平 12月19日北京九州一轨环境科技股份有限公司(简称&#xff1a;“九州一轨”&#xff09;日前通过注册&#xff0c;准备在科创板上市。九州一轨计划募资6.57亿元&#xff0c;其中&#xff0c;2.79亿元用于噪声与振动综合控制产研基地建设项目&#xff0c;1.43亿元用…

[附源码]计算机毕业设计Python飞越青少儿兴趣培训机构管理系统(程序+源码+LW文档)

该项目含有源码、文档、程序、数据库、配套开发软件、软件安装教程 项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等…

我的一周年创作纪念日

机缘 第一次写文章的时候&#xff0c;CSDN还是我平时课程设计的救星&#xff1b;第一次写文章的时候&#xff0c;还不知道有什么拿得出手、可以和大家分享的&#xff1b;第一次写文章的时候&#xff0c;幻想着自己一觉醒来就坐拥10w粉丝&#xff0c;哈哈哈。感谢自己曾经冒出的…

【实践】推荐、搜索、广告多业务多场景统一预估引擎实践与思考

省时查报告-专业、及时、全面的行研报告库省时查方案-专业、及时、全面的营销策划方案库【免费下载】2022年11月份热门报告盘点《底层逻辑》高清配图‍基于深度学习的个性化推荐系统实时化改造与升级.pdf推荐技术在vivo互联网商业化业务中的实践.pdf推荐系统基本问题及系统优化…

元认知神经网络与在线序贯学习(Matlab代码实现)

目录 &#x1f4a5;1 概述 &#x1f4da;2 运行结果 &#x1f389;3 参考文献 &#x1f468;‍&#x1f4bb;4 Matlab代码 &#x1f4a5;1 概述 文章包含用于实现自适应识别和控制的在线顺序学习算法、元认知神经网络和前馈神经网络的代码。这些方法也用于解决分类和时间序…

[附源码]计算机毕业设计Node.js仓库管理系统(程序+LW)

项目运行 环境配置&#xff1a; Node.js最新版 Vscode Mysql5.7 HBuilderXNavicat11Vue。 项目技术&#xff1a; Express框架 Node.js Vue 等等组成&#xff0c;B/S模式 Vscode管理前后端分离等等。 环境需要 1.运行环境&#xff1a;最好是Nodejs最新版&#xff0c;我…

【docker】CMD和ENTRYPOINT的区别

1、测试cmd #编写 dockerfile 文件 [rootkuangshen docekrfile]# vim dockerfile-cmd-test FROM centos CMD ["ls","-a"] #构建镜像 [rootkuangshen dockerfile]# docker build -f dockerfile-cmd-test -t cmdtest . #run运行&#xff0c;发现我们的ls -a …

你为什么一定要学Python?

我们为什么要学习Python&#xff1f; 在农业社会时&#xff0c;我们要学习驾驭马、驴、牛&#xff0c;让它们为我们出力、干活。 在工业社会时&#xff0c;我们要学会驾驭各种机器、火车、轮船、飞机、机床等等。 今天&#xff0c;我们要让机器听我们的指挥&#xff0c;我们就…

Python图像处理【5】图像扭曲/逆扭曲

图像扭曲/逆扭曲0. 前言1. 使用 scikit-image warp() 函数执行图像变换1.1 scikit-image warp() 函数原理1.2 利用 warp() 函数实现图像变换2. 漩涡变换详解2.1 旋涡变换原理2.2 使用 scikit-image warp() 实现旋涡变换2.3 使用 scipy.ndimage 实现漩涡变换3. 使用 scikit-imag…