【计算机组成原理】实验4

使用Verilog语言实现一个单周期CPU,测试平台:Vivado

①部分代码:

single_cycle_cpu.v:

`timescale 1ns / 1ps`define STARTADDR 32'd0  // 程序起始地址
module single_cycle_cpu(input clk,    // 时钟input resetn,  // 复位信号,低电平有效//display datainput  [ 4:0] rf_addr,input  [31:0] mem_addr,output [31:0] rf_data,output [31:0] mem_data,output [31:0] cpu_pc,output [31:0] cpu_inst);//---------------------------------{取指}begin------------------------------------//reg  [31:0] pc;wire [31:0] next_pc;wire [31:0] seq_pc;wire [31:0] jbr_target;wire jbr_taken;// 下一指令地址:seq_pc=pc+4assign seq_pc[31:2]    = pc[31:2] + 1'b1;assign seq_pc[1:0]     = pc[1:0];// 新指令:若指令跳转,为跳转地址;否则为下一指令assign next_pc = jbr_taken ? jbr_target : seq_pc;always @ (posedge clk)    // PC程序计数器beginif (!resetn) beginpc <= `STARTADDR; // 复位,取程序起始地址endelse beginpc <= next_pc;    // 不复位,取新指令endendwire [31:0] inst_addr;wire [31:0] inst;assign inst_addr = pc;  // 指令地址:指令长度32位inst_rom inst_rom_module(         // 指令存储器.addr      (inst_addr[6:2]),  // I, 5,指令地址.inst      (inst          )   // O, 32,指令);assign cpu_pc = pc;       //display pcassign cpu_inst = inst;
//----------------------------------{取指}end-------------------------------------////---------------------------------{译码}begin------------------------------------//wire [5:0] op;      //操作码 wire [4:0] rs;       // 源操作数1wire [4:0] rt;       // 源操作数2wire [4:0] rd;       // 目的操作数wire [4:0] sa;       // 特殊域,可能存放偏移量wire [5:0] funct;    // 功能码wire [15:0] imm;     // 立即数wire [15:0] offset;  // 地址偏移wire [25:0] target;  // 目标地址//补充以上变量的赋值,即译码 instassign op     = inst[31:26];  // 操作码assign rs     = inst[25:21];  // 源操作数1assign rt     = inst[20:16];  // 源操作数2assign rd     = inst[15:11];  // 目标操作数assign sa     = inst[10:6];   // 特殊域,可能存放偏移量assign funct  = inst[5:0];    // 功能码assign imm    = inst[15:0];   // 立即数assign offset = inst[15:0];   // 地址偏移量assign target = inst[25:0];   // 目标地址wire op_zero;  // 操作码全0wire sa_zero;  // sa域全0assign op_zero = ~(|op);assign sa_zero = ~(|sa);// 实现指令列表wire inst_ADDU, inst_SUBU , inst_SLT, inst_AND;wire inst_NOR , inst_OR   , inst_XOR, inst_SLL;wire inst_SRL , inst_ADDIU, inst_BEQ, inst_BNE;wire inst_LW  , inst_SW   , inst_LUI, inst_J;//补充:assign inst_ADDU  = op_zero & sa_zero    & (funct == 6'b100001);// 无符号加法assign inst_SUBU  = op_zero & sa_zero    & (funct == 6'b100011);// 无符号减法assign inst_SLT   = op_zero & sa_zero    & (funct == 6'b101010);// 小于则置位assign inst_AND   = op_zero & sa_zero    & (funct == 6'b100100);// 逻辑与运算assign inst_NOR   = op_zero & sa_zero    & (funct == 6'b100111);// 逻辑或非运算assign inst_OR    = op_zero & sa_zero    & (funct == 6'b100101);// 逻辑或运算assign inst_XOR   = op_zero & sa_zero    & (funct == 6'b100110);// 逻辑异或运算assign inst_SLL   = op_zero & (rs==5'd0) & (funct == 6'b000000);// 逻辑左移assign inst_SRL   = op_zero & (rs==5'd0) & (funct == 6'b000010);// 逻辑右移assign inst_ADDIU = (op == 6'b001001);                  // 立即数无符号加法assign inst_BEQ   = (op == 6'b000100);                  // 判断相等跳转assign inst_BNE   = (op == 6'b000101);                  // 判断不等跳转assign inst_LW    = (op == 6'b100011);                  // 从内存装载assign inst_SW    = (op == 6'b101011);                  // 向内存存储assign inst_LUI   = (op == 6'b001111);                  // 立即数装载高半字节assign inst_J     = (op == 6'b000010);                  // 直接跳转// 无条件跳转判断wire        j_taken;wire [31:0] j_target;assign j_taken  = inst_J;// 补充:无条件跳转目标地址:PC={PC[31:28],target<<2}assign j_target = {pc[31:28], target, 2'b00};//分支跳转wire        beq_taken;wire        bne_taken;wire [31:0] br_target;// 补充assign beq_taken = (rs_value == rt_value);       // BEQ跳转条件:GPR[rs]=GPR[rt]assign bne_taken = ~beq_taken;                   // BNE跳转条件:GPR[rs]≠GPR[rt]assign br_target[31:2] = pc[31:2] + {{14{offset[15]}}, offset};assign br_target[1:0]  = pc[1:0];    // 分支跳转目标地址:PC=PC+offset<<2//补充:跳转指令的跳转信号和跳转目标地址assign jbr_taken = j_taken              // 指令跳转:无条件跳转 或 满足分支跳转条件| inst_BEQ & beq_taken| inst_BNE & bne_taken;assign jbr_target = j_taken ? j_target : br_target;// 寄存器堆wire rf_wen;wire [4:0] rf_waddr;wire [31:0] rf_wdata;wire [31:0] rs_value, rt_value;regfile rf_module(.clk    (clk      ),  // I, 1.wen    (rf_wen   ),  // I, 1.raddr1 (rs       ),  // I, 5.raddr2 (rt       ),  // I, 5.waddr  (rf_waddr ),  // I, 5.wdata  (rf_wdata ),  // I, 32.rdata1 (rs_value ),  // O, 32.rdata2 (rt_value ),   // O, 32//display rf.test_addr(rf_addr),.test_data(rf_data));// 传递到执行模块的ALU源操作数和操作码wire inst_add, inst_sub, inst_slt,inst_sltu;wire inst_and, inst_nor, inst_or, inst_xor;wire inst_sll, inst_srl, inst_sra,inst_lui;assign inst_add = inst_ADDU | inst_ADDIU | inst_LW | inst_SW; // 做加法运算指令assign inst_sub = inst_SUBU; // 减法assign inst_slt = inst_SLT;  // 小于置位assign inst_sltu= 1'b0;      // 暂未实现assign inst_and = inst_AND;  // 逻辑与assign inst_nor = inst_NOR;  // 逻辑或非assign inst_or  = inst_OR;   // 逻辑或assign inst_xor = inst_XOR;  // 逻辑异或assign inst_sll = inst_SLL;  // 逻辑左移assign inst_srl = inst_SRL;  // 逻辑右移assign inst_sra = 1'b0;      // 暂未实现assign inst_lui = inst_LUI;  // 立即数装载高位wire [31:0] sext_imm;wire   inst_shf_sa;    //使用sa域作为偏移量的指令wire   inst_imm_sign;  //对立即数作符号扩展的指令assign sext_imm      = {{16{imm[15]}}, imm};// 立即数符号扩展assign inst_shf_sa   = inst_SLL | inst_SRL;assign inst_imm_sign = inst_ADDIU | inst_LUI | inst_LW | inst_SW;wire [31:0] alu_operand1;wire [31:0] alu_operand2;wire [11:0] alu_control;assign alu_operand1 = inst_shf_sa ? {27'd0,sa} : rs_value;assign alu_operand2 = inst_imm_sign ? sext_imm : rt_value;assign alu_control = {inst_add,        // ALU操作码,独热编码inst_sub,inst_slt,inst_sltu,inst_and,inst_nor,inst_or, inst_xor,inst_sll,inst_srl,inst_sra,inst_lui};
//----------------------------------{译码}end-------------------------------------////---------------------------------{执行}begin------------------------------------//wire [31:0] alu_result;alu alu_module(.alu_control  (alu_control ),  // I, 12, ALU控制信号.alu_src1     (alu_operand1),  // I, 32, ALU操作数1.alu_src2     (alu_operand2),  // I, 32, ALU操作数2.alu_result   (alu_result  )   // O, 32, ALU结果);
//----------------------------------{执行}end-------------------------------------////---------------------------------{访存}begin------------------------------------//wire [3 :0] dm_wen;wire [31:0] dm_addr;wire [31:0] dm_wdata;wire [31:0] dm_rdata;assign dm_wen   = {4{inst_SW}} & resetn;    // 内存写使能,非resetn状态下有效assign dm_addr  = alu_result;               // 内存写地址,为ALU结果assign dm_wdata = rt_value;                 // 内存写数据,为rt寄存器值data_ram data_ram_module(.clk   (clk         ),  // I, 1,  时钟.wen   (dm_wen      ),  // I, 1,  写使能.addr  (dm_addr[6:2]),  // I, 32, 读地址.wdata (dm_wdata    ),  // I, 32, 写数据.rdata (dm_rdata    ),  // O, 32, 读数据//display mem.test_addr(mem_addr[6:2]),.test_data(mem_data     ));
//----------------------------------{访存}end-------------------------------------////---------------------------------{写回}begin------------------------------------//wire inst_wdest_rt;   // 寄存器堆写入地址为rt的指令wire inst_wdest_rd;   // 寄存器堆写入地址为rd的指令//补充assign inst_wdest_rt = inst_ADDIU | inst_LW | inst_LUI;assign inst_wdest_rd = inst_ADDU | inst_SUBU | inst_SLT | inst_AND | inst_NOR| inst_OR   | inst_XOR  | inst_SLL | inst_SRL; //补充assign rf_wen   = (inst_wdest_rt | inst_wdest_rd) & resetn; // 寄存器堆写使能信号,非复位状态下有效assign rf_waddr = inst_wdest_rd ? rd : rt;        // 寄存器堆写地址rd或rtassign rf_wdata = inst_LW ? dm_rdata : alu_result;// 写回结果,为load结果或ALU结果
//----------------------------------{写回}end-------------------------------------//
endmodule

TestBench.v:

`timescale 1ns / 1psmodule tb;// Inputsreg clk;reg resetn;reg [4:0] rf_addr;reg [31:0] mem_addr;// Outputswire [31:0] rf_data;wire [31:0] mem_data;wire [31:0] cpu_pc;wire [31:0] cpu_inst;// Instantiate the Unit Under Test (UUT)single_cycle_cpu uut (.clk(clk), .resetn(resetn), .rf_addr(rf_addr), .mem_addr(mem_addr), .rf_data(rf_data), .mem_data(mem_data), .cpu_pc(cpu_pc), .cpu_inst(cpu_inst));initial begin// Initialize Inputsclk = 1;resetn = 0;rf_addr = 0;mem_addr = 0;#50;resetn = 1;rf_addr = 1;#10;rf_addr = 2;#10;rf_addr = 3;#10;       rf_addr = 4;#10;  rf_addr = 5;#10;mem_addr = 32'H00000014;#10;          rf_addr = 6;#10;      rf_addr = 7;#10;      rf_addr = 8;#10;       rf_addr = 9;#10;mem_addr = 32'H0000001c;   #10;      rf_addr = 10;#10;       rf_addr = 11;mem_addr = 32'H00000000;#10;endalways #5 clk=~clk;
endmodule

inst_rom.v:

`timescale 1ns / 1psmodule inst_rom(input      [4 :0] addr, // 指令地址output reg [31:0] inst       // 指令);wire [31:0] inst_rom[19:0];  // 指令存储器,字节地址7'b000_0000~7'b111_1111//------------- 指令编码 ---------|指令地址|--- 汇编指令 -----|- 指令结果 -----//assign inst_rom[ 0] = 32'h24010001; // 00H: addiu $1 ,$0,#1   | $1 = 0000_0001Hassign inst_rom[ 1] = 32'h00011100; // 04H: sll   $2 ,$1,#4   | $2 = 0000_0010Hassign inst_rom[ 2] = 32'h00411821; // 08H: addu  $3 ,$2,$1   | $3 = 0000_0011Hassign inst_rom[ 3] = 32'h00022082; // 0CH: srl   $4 ,$2,#2   | $4 = 0000_0004Hassign inst_rom[ 4] = 32'h00642823; // 10H: subu  $5 ,$3,$4   | $5 = 0000_000DHassign inst_rom[ 5] = 32'hAC250013; // 14H: sw    $5 ,#19($1) | Mem[0000_0014H] = 0000_000DHassign inst_rom[ 6] = 32'h00A23027; // 18H: nor   $6 ,$5,$2   | $6 = FFFF_FFE2Hassign inst_rom[ 7] = 32'h00C33825; // 1CH: or    $7 ,$6,$3   | $7 = FFFF_FFF3Hassign inst_rom[ 8] = 32'h00E64026; // 20H: xor   $8 ,$7,$6   | $8 = 0000_0011Hassign inst_rom[ 9] = 32'hAC08001C; // 24H: sw    $8 ,#28($0) | Mem[0000_001CH] = 0000_0011Hassign inst_rom[10] = 32'h00C7482A; // 28H: slt   $9 ,$6,$7   | $9 = 0000_0001Hassign inst_rom[11] = 32'h08000000; // 4CH: j     00H         | 跳转指令00H//读指令,取4字节always @(*)begincase (addr)5'd0 : inst <= inst_rom[0 ];5'd1 : inst <= inst_rom[1 ];5'd2 : inst <= inst_rom[2 ];5'd3 : inst <= inst_rom[3 ];5'd4 : inst <= inst_rom[4 ];5'd5 : inst <= inst_rom[5 ];5'd6 : inst <= inst_rom[6 ];5'd7 : inst <= inst_rom[7 ];5'd8 : inst <= inst_rom[8 ];5'd9 : inst <= inst_rom[9 ];5'd10: inst <= inst_rom[10];5'd11: inst <= inst_rom[11];5'd12: inst <= inst_rom[12];5'd13: inst <= inst_rom[13];5'd14: inst <= inst_rom[14];5'd15: inst <= inst_rom[15];5'd16: inst <= inst_rom[16];5'd17: inst <= inst_rom[17];5'd18: inst <= inst_rom[18];5'd19: inst <= inst_rom[19];default: inst <= 32'd0;endcaseend
endmodule

其他源文件包括:(regfile.v)(alu.v)(adder.v)(data_ram.v)

实验要求中已给出。

(附:全文文件下载地址:(88条消息) 【计算机组成原理实验】单周期cpu的实现_源码文件-单片机文档类资源-CSDN文库

②仿真图像及其分析:

使能==1时开始,

先向$1写入数据0000_0001H,

然后将$1数据逻辑左移并存入$2,

然后将$1与$2相加存于$3,

然后将$2逻辑右移存入$4,

随后$3减$4,存入$5,将结果存入地址为0000_0014H的mem中,

随后将$5和$2做或非运算,存入$6,

随后将$6和$3做或运算,存入$7,

随后将$7和$6做异或运算,存入$8,

随后将$8中数据写入地址为0000_001CH的mem中。

最后进行跳转指令跳转到开头的00H指令。

【计算机组成原理】实验4:单周期CPU(Verilog)中海大相关推荐

  1. 【中山大学计算机组成原理实验】单周期CPU设计与实现

    实验一 : 单周期CPU设计与实现 一. 实验目的 (1) 掌握单周期CPU数据通路图的构成.原理及其设计方法: (2) 掌握单周期CPU的实现方法,代码实现方法: (3) 认识和掌握指令与CPU的关 ...

  2. 计算机组成原理 实验五 单周期cpu

    proteus仿真软件安装教程链接 如果对我的实验报告感兴趣,可以考虑我的计组实验专栏 计算机组成原理专栏链接

  3. 计算机组成原理实验单周期处理,计算机组成原理实验实验报告-单周期cpu设计...

    计算机组成原理实验实验报告-单周期cpu设计 (16页) 本资源提供全文预览,点击全文预览即可全文预览,如果喜欢文档就下载吧,查找使用更方便哦! 19.90 积分 计算机组成原理实验计算机组成原理实验 ...

  4. 单周期CPU——verilog语言实现

    单周期CPU的设计与实现 关于单周期CPU的设计问题,相信各位在课程上也有所学习,以下是个人的一些理解 整个项目的资源下载:这里写链接内容 实验内容 基本要求 PC和寄存器组写状态使用时钟触发,这是必 ...

  5. 计算机组成原理R寄存器组,计算机组成原理实验的探讨论文(2)

    计算机组成原理实验的探讨论文篇二 <计算机组成原理实验初探> 摘要:根据国内外计算机硬件类实践课程教育的现状,分析传统计算机组成原理实验课程教学中的弊端,介绍南京大学计算机系对此门实验课的 ...

  6. 计算机组成原理 微地址设置MLD,计算机组成原理实验

    <计算机组成原理实验>由会员分享,可在线阅读,更多相关<计算机组成原理实验(23页珍藏版)>请在技术文库上搜索. 1.计算机组成原理实验23实验2微地址+1操作置MLD=1.按 ...

  7. 合肥工业大学宣城校区计算机组成原理实验 单周期 CPU 设计与实现

    本实验使用的是Verilog,离谱的是CSDN居然找不到Verilog的代码块,只能使用c语言的代码块了. 一.实验目的: 通过设计并实现支持 10 条指令的CPU,进一步理解和掌握CPU 设计的基本 ...

  8. 计算机公共基础知识实验报告,MIPS单周期CPU实验报告总结.doc

    <计算机组成原理实验> 实验报告 (实验二) 学 院 名 称 : 专业(班级) : 学 生 姓 名 : 学号 : 时间:2017年11月25日 成 绩 : 实 验 二 : 单周期 CPU设 ...

  9. 计算机组成原理实验2---单周期CPU

    实验目的 实验内容 设计一个单周期CPU,该CPU至少能实现以下指令功能操作. 必须写一段测试用的汇编程序,而且必须包含所要求的所有指令,slti指令必须检查两种情况:"小于"和& ...

最新文章

  1. 机械键盘连击怎么处理_怎么选择机械键盘?各种平价机械键盘推荐
  2. Android第二十期 - 微信的主体构架
  3. 二层以太网技术—Vecloud
  4. Taro+react开发(36)每一个节点要一个view包裹
  5. SAP RFC user 最小权限
  6. wgs utm java,Java,将经纬度转换为UTM
  7. 7-48 字符串输入练习 (I) (15 分)
  8. window php composer,Window下安装php composer
  9. 【081】◀▶ HTML CSS 学习
  10. 正交表测试与混合正交表工具
  11. linux 中文乱码 解决方法
  12. ES6(ECMAScript6)知识总结(二)
  13. 自建exchange邮箱有什么成熟的超大附件解决方案?
  14. leetcode — 46. 全排列(不含重复数字)
  15. 换一种姿势挖掘任意用户密码重置漏洞
  16. 如何在知网下载硕士、博士论文PDF?
  17. Java集合--阻塞队列(ArrayBlockingQueue)
  18. 【OpenGL学习笔记五】 索引缓冲对象EBO
  19. 宽带射频放大器OA4SMM4(1)
  20. [HTML/JS]使用JS新年倒计时

热门文章

  1. 利用正则表达式处理内容数据(Python数据清洗)
  2. Pop Sequence
  3. Excel中设置内边框和外边框
  4. 简明入门讲义——DNS架构是如何发展的
  5. 人工智能技术与产业发展
  6. 【硬刚大数据】从零到大数据专家之数据仓库体系建模实施注意事项小总结
  7. 基于php的个人理财系统,基于PHP个人理财管理系统设计
  8. 赛门铁克企业版中DOscan和Rtvscan进程占用大量内存的解决办法
  9. 没有理由拒绝的四款实用软件,让你办公无所不能
  10. 算法(逻辑)优劣评估方法