一、06-Minisys-1单周期CPU控制器的设计(1)

1.主要内容:

  1. 创建一个项目
  2. 单周期CPU控制器设计

项目初始文件http://www.njyangqs.com/soc/download/

2.创建一个项目

  1. 先确保初始文件包已安装在C盘的minisys1_classfiles目录下
  2. 打开vivado(2015.4),创建新项目,在C盘minisys1下
  3. 添加source files时,C盘-minisys1_classfiles-minisys,勾选copy。

    4. 添加约束文件,xdc文件夹,勾上copy。
  4. 选择器件,Artix-7家族,fgg484封装,-1速度,选最下面的器件。
  5. 所有.v文件都不完整,需要补充完整
// ifetc32.v`timescale 1ns / 1ps
//
module Ifetc32(Instruction,PC_plus_4_out,Add_result,Read_data_1,Branch,nBranch,Jmp,Jal,Jrn,Zero,clock,reset,opcplus4);output[31:0] Instruction;         // 输出指令output[31:0] PC_plus_4_out;input[31:0]  Add_result;input[31:0]  Read_data_1;input        Branch;input        nBranch;input        Jmp;input        Jal;input        Jrn;input        Zero;input        clock,reset;output[31:0] opcplus4;wire[31:0]   PC_plus_4;reg[31:0]      PC;reg[31:0]    next_PC; wire[31:0]   Jpadr;reg[31:0]    opcplus4;//分配64KB ROM,编译器实际只用 64KB ROMprgrom instmem(.clka(clock),         // input wire clka.addra(PC[15:2]),     // input wire [13 : 0] addra.douta(Jpadr)         // output wire [31 : 0] douta);assign Instruction = Jpadr;              //  取出指令always @* begin                          // beq $n ,$m if $n=$m branch   bne if $n /=$m branch jrendalways @(negedge clock) beginend
endmodule
// idecode32.v
`timescale 1ns / 1ps
//module Idecode32(read_data_1,read_data_2,Instruction,read_data,ALU_result,Jal,RegWrite,MemtoReg,RegDst,Sign_extend,clock,reset,opcplus4,read_register_1_address);output[31:0] read_data_1;output[31:0] read_data_2;input[31:0]  Instruction;input[31:0]  read_data;                   //  从DATA RAM or I/O port取出的数据input[31:0]  ALU_result;                  //  需要扩展立即数到32位input        Jal; input        RegWrite;input        MemorIOtoReg;input        RegDst;output[31:0] Sign_extend;input      clock,reset;input[31:0]  opcplus4;                 // 来自取指单元,JAL中用output[4:0] read_register_1_address;wire[31:0] read_data_1;wire[31:0] read_data_2;reg[31:0] register[0:31];              //寄存器组共32个32位寄存器reg[4:0] write_register_address;reg[31:0] write_data;wire[4:0] read_register_2_address;wire[4:0] write_register_address_1;wire[4:0] write_register_address_0;wire[15:0] Instruction_immediate_value;wire[5:0] opcode;wire sign;always @* begin                                            //这个进程指定不同指令下的目标寄存器endalways @* begin  //这个进程基本上是实现结构图中右下的多路选择器,准备要写的数据endinteger i;always @(posedge clock) begin       // 本进程写目标寄存器if(reset==1) begin              // 初始化寄存器组for(i=0;i<32;i=i+1) register[i] <= i;end else if(RegWrite==1) begin  // 注意寄存器0恒等于0endend
endmodule
// control32.v`timescale 1ns / 1ps
//
module control32(Opcode,Function_opcode,Jrn,RegDST,ALUSrc,MemtoReg,RegWrite,MemWrite,Branch,nBranch,Jmp,Jal,I_format,Sftmd,ALUOp);input[5:0]   Opcode;            // 来自取指单元instruction[31..26]input[5:0]   Function_opcode;     // r-form instructions[5..0]output       Jrn;output       RegDST;output       ALUSrc;            // 决定第二个操作数是寄存器还是立即数output       MemtoReg;output       RegWrite;output       MemWrite;output       Branch;output       nBranch;output       Jmp;output       Jal;output       I_format;output       Sftmd;output[1:0]  ALUOp;wire Jmp,I_format,Jal,Branch,nBranch;wire R_format,Lw,Sw;assign R_format = (Opcode==6'b000000)? 1'b1:1'b0;      //--00h assign RegDST = R_format;                               //说明目标是rd,否则是rtendmodule
// executs32.v`timescale 1ns / 1ps
//module Executs32(Read_data_1,Read_data_2,Sign_extend,Function_opcode,Exe_opcode,ALUOp,Shamt,ALUSrc,I_format,Zero,Sftmd,ALU_Result,Add_Result,PC_plus_4);input[31:0]  Read_data_1;     //r-form rsinput[31:0]  Read_data_2;        //r-form rtinput[31:0]  Sign_extend;        //i-forminput[5:0]   Function_opcode;   //r-form instructions[5..0]input[5:0]   Exe_opcode;         //op codeinput[1:0]   ALUOp;input[4:0]   Shamt;input         Sftmd;input        ALUSrc;input        I_format;output       Zero;output[31:0] ALU_Result;output[31:0] Add_Result;     //pc op        input[31:0]  PC_plus_4;reg[31:0] ALU_Result;wire[31:0] Ainput,Binput;reg[31:0] Cinput,Dinput;reg[31:0] Einput,Finput;reg[31:0] Ginput,Hinput;reg[31:0] Sinput;reg[31:0] ALU_output_mux;wire[32:0] Branch_Add;wire[2:0] ALU_ctl;wire[5:0] Exe_code;wire[2:0] Sftm;wire Sftmd;reg s;assign Sftm = Function_opcode[2:0];   // 实际有用的只有低三位(移位指令)assign Exe_code = (I_format==0) ? Function_opcode : {3'b000,Exe_opcode[2:0]};assign Ainput = Read_data_1;assign Binput = (ALUSrc == 0) ? Read_data_2 : Sign_extend[31:0]; //R/LW,SW  sft  else的时候含LW和SWassign ALU_ctl[0] = (Exe_code[0] | Exe_code[3]) & ALUOp[1];      //24H AND assign ALU_ctl[1] = ((!Exe_code[2]) | (!ALUOp[1]));assign ALU_ctl[2] = (Exe_code[1] & ALUOp[1]) | ALUOp[0];always @* begin  // 6种移位指令if(Sftmd)case(Sftm[2:0])3'b000:Sinput =             //Sll rd,rt,shamt  000003'b010:Sinput =               //Srl rd,rt,shamt  000103'b100:Sinput =                    //Sllv rd,rt,rs 0001003'b110:Sinput =                    //Srlv rd,rt,rs 0001103'b011:Sinput =                  //Sra rd,rt,shamt 000113'b111:Sinput =                //Srav rd,rt,rs 00111default:Sinput = Binput;endcaseelse Sinput = Binput;endalways @* beginif(((ALU_ctl==3'b111) && (Exe_code[3]==1))||((ALU_ctl[2:1]==2'b11) && (I_format==1))) //slti(sub)  处理所有SLT类的问题ALU_Result =   ;else if((ALU_ctl==3'b101) && (I_format==1)) ALU_Result[31:0] =   ;else if(Sftmd==1) ALU_Result =   ; else  ALU_Result = ALU_output_mux[31:0]; //otherwiseendassign Branch_Add = PC_plus_4[31:2] + Sign_extend[31:0];assign Add_Result = Branch_Add[31:0];   //算出的下一个PC值已经做了除4处理,所以不需左移16位assign Zero = (ALU_output_mux[31:0]== 32'h00000000) ? 1'b1 : 1'b0;always @(ALU_ctl or Ainput or Binput) begincase(ALU_ctl)3'b000:ALU_output_mux = 3'b001:ALU_output_mux = 3'b010:ALU_output_mux =  3'b011:ALU_output_mux = 3'b100:ALU_output_mux = 3'b101:ALU_output_mux = 3'b110:ALU_output_mux = 3'b111:ALU_output_mux = default:ALU_output_mux = 32'h00000000;endcaseend
endmodule
//dmemory32.v`timescale 1ns / 1ps
//
module dmemory32(read_data,address,write_data,Memwrite,clock);output[31:0] read_data;input[31:0] address;     //来自memorio模块,源头是来自执行单元算出的alu_resultinput[31:0] write_data;  //来自译码单元的read_data2input  Memwrite;         //来自控制单元input  clock;wire clk;assign clk = !clock;     //  因为使用Cyclone芯片的固有延迟,RAM的地址线来不及在时钟上升沿准备好,//  使得时钟上升沿数据读出有误,所以采用反相时钟,使得读出数据比地址准//  备好要晚大约半个时钟,从而得到正确地址。//分配64KB RAM,编译器实际只用 64KB RAMendmodule
// memorio.v`timescale 1ns / 1ps
//module memorio(caddress,address,memread,memwrite,ioread,iowrite,mread_data,ioread_data,wdata,rdata,write_data,LEDCtrl,SwitchCtrl);input[31:0] caddress;       // from alu_result in executs32input memread;               // read memory, from control32input memwrite;               // write memory, from control32input ioread;                // read IO, from control32input iowrite;                // write IO, from control32input[31:0] mread_data;      // data from memoryinput[15:0] ioread_data; // data from ioinput[31:0] wdata;           // the data from idecode32,that want to write memory or iooutput[31:0] rdata;           // data from memory or IO that want to read in registeroutput[31:0] write_data;    // data to memory or I/Ooutput[31:0] address;       // address to mAddressoutput LEDCtrl;                // LED CSoutput SwitchCtrl;          // Switch CSreg[31:0] write_data;wire iorw;assign  address = caddress;assign  rdata = (memread==1) ? mread_data : {16'h0000,ioread_data[15:0]};assign  iorw = (iowrite||ioread);assign  LEDCtrl = ((iorw==1) && (caddress[31:0] == 32'hFFFFFC60)) ? 1'b1:1'b0;assign  SwitchCtrl = ((iorw==1) && (caddress[31:0] == 32'hFFFFFC70)) ? 1'b1:1'b0;always @* beginif((memwrite==1)||(iowrite==1)) beginwrite_data = wdata;end else beginwrite_data = 32'hZZZZZZZZ;endend
endmodule
//ioread.v`timescale 1ns / 1ps
//module ioread(reset,clk,ior,switchctrl,ioread_data,ioread_data_switch);input reset,clk;input ior,switchctrl;input[15:0] ioread_data_switch;output[15:0] ioread_data;reg[15:0] ioread_data;always @* beginif(reset == 1)ioread_data = 16'b0000000000000000;else if(ior == 1) beginif(switchctrl == 1)ioread_data = ioread_data_switch;elseioread_data = ioread_data;endend
endmodule
// leds.v`timescale 1ns / 1ps
//module leds(led_clk,ledrst,ledwrite,ledaddrcs,ledwdata,ledout);input led_clk,ledrst;input ledwrite;input ledaddrcs;input[15:0] ledwdata;output[15:0] ledout;reg [15:0] ledout;always@(posedge led_clk or posedge ledrst) beginend
endmodule
// switchs.v`timescale 1ns / 1ps
//module switchs(switclk,switrst,switchread,switchaddrcs,switchrdata,switch_i);input switclk,switrst;input switchaddrcs,switchread;output [15:0] switchrdata;//拨码开关输入input [15:0] switch_i;reg [15:0] switchrdata;always@(negedge switclk or posedge switrst) beginend
endmodule

3.设计方法

  1. 考查每条指令在数据通路中的执行过程和涉及的控制信号的取值
  2. 根据列出的指令和控制信号之间的关系,写出每个控制信号的逻辑表达式
  3. 控制信号:

4.工程文件中control32.v

输入输出信号

控制单元输入信号来自于取值单元的指令码、以及指令中的功能码

控制单元的输出信号,各种控制信号,数据通路中一个个添加进来的

5.RegDST设计举例

1.将所有指令列表,OP值、操作码、RegDST取值

同类型可综合

2.RegDST数值
在I类型数据通路设计时,目标寄存器,R类型为rd,I类型为rt,需要选择为rd还是rt。二选一多路选择器的控制端为RegDST。
RegDST=1 -> rd
RegDST=0 -> rt

3.类型分析
ori addiu lw sw beq:I类型 (lw sw 存储器存储的指令)
jump J类型
R-format R类型

I类型RegDST取0,目标寄存器为rt;
R类型RegDST取1,目标寄存器为rd。
sw beq jump不写寄存器,只跳转/数据写存储器,RegDST取哪个无所谓。

4.RegDST = R-format
考察op

指令码OP code=0时,R-format为1,

二、06-Minisys-1单周期CPU控制器的设计(2)

1.RegWrite设计举例


1.写寄存器
I-format有些指令写寄存器,有些不写
jr不写寄存器
lw把存储器内容写寄存器,为1
sw无所谓,将寄存器的值写存储器中
jal跳转前把PC+4值写寄存器中
j跳转,不写
R-format写rd寄存器

2.练习1

3.在Minisys-1中哪些指令会使RegWrite为1,哪些指令会使RegWrite为0?
除beq、bne、lw、sw以外的I类型指令,以及R-format指令,还有jal指令,因此我们可以先定义I-format、lw、jal、jrn信号,再定义RegWrite。

4.练习2

2.ALU的控制电路

1.control32.v中发现有ALUop信号是输出出去的,输出给执行单元,告诉执行单元指令属于哪些类型。
ALU采用分级控制的方法(减轻控制器负担)。
在控制器中,只发出ALUop信号

2.约定:

3.这些指令到了运算/执行单元都要计算的。
LW、SW做加法得到最终地址,运算完成后当地址使用;
BEQ、BNE做减法,判断是否相等,运算完成后通过结果指导下一步工作;
R、I-format有各种运算,运算完成后即为最终结果。

4.如何实现
拼接运算,高位R-format或I-format成立,低位Branch或nBranch成立。
ALUop会送到执行单元,执行单元会根据ALUop或另外的控制信号确定做什么运算。

5.分级
对于执行单元来说,它的控制是分级的,一部分在控制单元中生成ALUop还有一部分在执行单元中生成更详细的控制信号。

6.练习3
完整地写出控制器模块。

3.ALU的控制电路仿真

  1. 在仿真前对设计的控制器的模块进行综合,看看有没有问题。control32-set as top做成顶层文件,对它进行综合。

  2. 看project summary,没有错误关闭当前窗口。
  3. 准备仿真,添加仿真文件,sim-control32_sim.v,并设置为顶层文件
  4. 查看control32_sim.v,所有输入都为reg,输出都为wire
  5. 对control32模块进行元件实例化
  6. 对control32产生一些输入信号检查输出是否正确,输入已有opcode和functioncode,每间隔200nm/250nm改变指令
  7. 进行行为仿真,双击波形图bar,选择3μs,reset-start,调整波形

  • ADD要写寄存器,RegWrite为1;
  • JR,Jrn信号为1;
  • ADDI,ALUSrc为1,选择立即数,同时RegWrite为1要写寄存器;
  • LW,从存储器中读数据给寄存器,MemtoReg为1,ALUSrc为1属于I类型;
  • SW,MemWrite为高电平;
  • BEQ,Branch高电平,nBranch低电平;
  • BNE,Branch低电平,nBranch高电平;
  • JMP,Jmp高电平;
  • JAL,Jal高电平;
  • SRL,移位指令,sftmd变为高电平

06-Minisys-1单周期CPU控制器的设计相关推荐

  1. 单周期CPU设计(Verilog)

    2017/06/08: 当时单周期cpu写的比较仓促,没有深入的进行调试,我准备在放假的时候重构一下代码, 然后把博文改进一下,现在实在没有时间,很抱歉~ 不过多周期我有调试过的,所以有需要的可以移步 ...

  2. 【Computer Organization笔记10】单周期CPU设计:基于7条MIPS指令的数据通路

    本次笔记内容: P19 计算机组成原理(19) P20 计算机组成原理(20) 本节课对应幻灯片: 组成原理24 singlecycle.pptx 基于上节课的7条MIPS指令的数据通路,分别针对7条 ...

  3. 单周期CPU设计【Verilog】

    第一章 单周期CPU的设计原理 1.1 单周期CPU概述 1.2 CPU工作原理 第二章 单周期CPU的设计内容 2.1 指令系统的设计 2.1.1 概述 2.1.2 运算类指令的设计 2.1.3 传 ...

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

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

  5. (Verilog)单周期CPU设计

    (Verilog)单周期CPU设计 首先是基础资料部分(借用学校资料): 一.实验内容 设计一个单周期CPU,该CPU至少能实现以下指令功能操作.需设计的指令与格式如下: ==> 算术运算指令 ...

  6. MIPS单周期CPU设计(24条指令)

    MIPS单周期可执行24条指令CPU 实验要求 本实训项目帮助学生构建支持 24 条指令的 MIPS 单周期 CPU ,最终实现的处理器能运行 benchmark 测试程序.另外希望学有余力的同学能为 ...

  7. 31条指令单周期cpu设计(Verilog)-(十)上代码→顶层模块设计总结

    说在前面 开发环境:Vivado 语言:Verilog cpu框架:Mips 控制器:组合逻辑 设计思路 按照预先设计好的数据通路图将各个模块连接起来 `timescale 1ns / 1ps mod ...

  8. 31条指令单周期cpu设计(Verilog)-(二)总体设计

    目录 31条指令单周期cpu设计(Verilog)-(一)相关软件 31条指令单周期cpu设计(Verilog)-(二)总体设计 31条指令单周期cpu设计(Verilog)-(三)指令分析      ...

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

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

最新文章

  1. 团队-科学技术器-模块测试过程
  2. matlab 由移相角如何产生移相脉冲,整流电路控制角移相范围是怎么确定的?
  3. 【debug】mount: unknown filesystem type ‘nfs’
  4. 今日头条、快手们疯狂招人是人工智能的失败?
  5. nmon安装为什么重启mysql_Centos7部署nmon监控工具
  6. [转]十个让你变成糟糕的程序员的行为
  7. Linux系统调用之open(), close() (转载)
  8. python dict()函数的奇异之处
  9. 已知圆上两点坐标和半径求圆心
  10. 服务器中的虚拟化是什么意思,虚拟化是什么意思
  11. oracle pdb与cdb区别,浅谈oracle 12C的新特性-CDB和PDB
  12. pig java api_Pig安装及入门案例
  13. INT8量化原理理解
  14. IPEmotion新增功能:交流电功率分析计算
  15. C语言简单编程案例——(五)
  16. 中国软件,从繁荣走向文明
  17. 多种JS刷新页面代码!
  18. 免费开源磁带机备份软件_服务器备份和还原过程| 免费和开源软件
  19. 宝塔使用心得--快速部署javaweb应用
  20. 字节(byte)、位(bit)、KB、B、字符之间关系以及编码占用位数

热门文章

  1. Android中录音的使用
  2. 教学质量分析系统 php,教学质量分析系统
  3. 关于 InnoDB 存储引擎的一些总结!
  4. 读书笔记:《北大管理课》
  5. redis使用普通用户启动
  6. 怎样把书读得“四通八达”?(文/王路)
  7. 大量教程+工具+源码下载地址汇总
  8. Clickhouse 官方测试数据集之SSB
  9. HTML中透明度的设置调整
  10. Mybatis插件处理createTime和updateTime