verilog实现的五级流水简易CPU(带板极验证) |
您所在的位置:网站首页 › 五级流水线cpu设计方案 › verilog实现的五级流水简易CPU(带板极验证) |
实现一个简易的五级流水的CPU,解决Hazard,并实现板极验证。 1 设计总览
2 实现原理 根据Top view 将整个CPU分为3个模块: 1 PCPU 主要模块:用从指令内存得到的指令进行运算处理,并从数据内存中写入或读取数据。这是最核心的部分,其他模块都很好设计。 2 Instruction_Mem 指令模块: 为PCPU模块提供指令,使得PCPU中通过指令寄存器中的值,找到指令的内存地址,从而读取指令。 3 Data_Mem 数据模块: PCPU从中读取数据或写入数据 板极验证: 用4个开关表示选择哪一个数据显示,用4个7段数码管显示数字
3 整个PCPU的工作流程: 五级流水: 注释: IF : 从指令模块中,通过指令寄存器PC寻址,获得指令。 ID: 解码指令,根据操作码提取要用到的数据输入通用寄存器。 EX: ALU运算单元在指令的调度下,使用之前通用寄存器中的数据根据不同指令完成不同运算。运算后将结果输出到reg_C中,并设置各个标记位的值。 MEM:这里主要是针对LOAD,STORE这类的读写指令要用到的。对于其他指令没有特别要求。 WB:回写把计算结果写入指令的左值中,这里除了跳转指令和load,store指令,都是写回第一个操作数(寄存器)
4 需要实现的汇编指令
5 分阶段实现优化过程 阶段一 : 实现最基本的cpu(没有指令存储器,数据存储器,没有解决hazard,没有板极验证,什么也没有…) 完成步骤: 步骤1:理解流水线工作原理 上课时流水线是听懂了,寄存器赋值,取数这些基本原理大概弄懂了。不过实际操作还是有很多要注意的。 步骤2:开始逐级编写基本代码 有了老师给的样例代码,整个框架基本构建好了。所以要做的就是弄清楚每个指令在每一级流水中需要做些什么,然后在每一级流水中再总结这些操作的共同点,不同点,需要特别注意的地方。 1)指令操作码的设计: 优化:这里考虑了一下控制指令的特殊性,因为控制指令在流水每一级操作中有很大相似性,所以为了简化电路,还有判断时代码的简化,把所有控制指令的前两位设为“11”,而其他指令前两位都不是“11”。这样编写代码的时候更容易理清逻辑,综合的时候电路也简单一些。 2)指令各级流水的设计: 这里思考了很多,设计每一条指令都需要特别小心,最重要的是在ID和EX还有ALUo中。 总结一下,主要就是整个16 bits的指令在流水线的每一步中起到“指挥”作用,然后每一级流水的工作就是在上一级完成后,利用
A ID中的寄存器赋值: reg_A 和 reg_B中存储的是在指令右边将要送入ALU参与运算的值。 由于指令的右边通常声明的是寄存器的编号(因为用户只能对通用寄存器进行操作,无法直接访问内存)或者立即数,所以要通过编号找到确定的寄存器,再将该通用寄存器里的值赋给reg_A 或者 reg_B。 优化: 这里为了减少reg_A 和 reg_B的翻转,考虑了一些优化。比如把要用到立即数的指令的立即数不写入寄存器,而是在下一级流水中之间从指令中取数。 B ex中ALUo的计算 主要就是用verilog本身的运算直接操作。运算后赋值个ALUo寄存器和cf标志位。 优化:比如一些用立即数的操作,之前没有存入reg_A 和 reg_B,直接从ex_ir中取数计算。 C mem中的读写 主要要和data模块进行数据传输,指令就是load和store。 D wb中写回运算结果 由于算数指令和逻辑运算指令基本都是要写回到寄存器。所以这里判断为:非跳转指令,非store,load指令,则写回第一个操作数(寄存器)。 6 源代码 1).v `timescale 1ns / 1ps // // Company: // Engineer: // // Create Date: 14:15:05 12/18/2014 // Design Name: // Module Name: CPU // Project Name: // Target Devices: // Tool versions: // Description: // // Dependencies: // // Revision: // Revision 0.01 - File Created // Additional Comments: // // // 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 SUB 5'b01011 `define SUBI 5'b10011 `define SUBC 5'b10111 `define CMP 5'b01100 // control `define JUMP 5'b11000 `define JMPR 5'b11001 `define BZ 5'b11010 `define BNZ 5'b11011 `define BN 5'b11100 `define BNN 5'b11101 `define BC 5'b11110 `define BNC 5'b11111 // logic / shift `define AND 5'b01101 `define OR 5'b01111 `define XOR 5'b01110 `define SLL 5'b00100 `define SRL 5'b00110 `define SLA 5'b00101 `define SRA 5'b00111 // general register `define gr0 3'b000 `define gr1 3'b001 `define gr2 3'b010 `define gr3 3'b011 `define gr4 3'b100 `define gr5 3'b101 `define gr6 3'b110 `define gr7 3'b111 // FSM `define idle 1'b0 `define exec 1'b1 /******* the whole module CPU is made of Instuction_Mem module, PCPU module and Data_Mem module ********/ module CPU( input wire clk, clock, enable, reset, start, input wire[3:0] select_y, output [7:0] select_segment, output [3:0] select_bit ); wire[15:0] d_datain; wire[15:0] i_datain; wire[7:0] d_addr; wire[7:0] i_addr; wire[15:0] d_dataout; wire d_we; wire[15:0] y; reg [20:0] count = 21'b0; Instruction_Mem instruction(clock,reset,i_addr,i_datain); PCPU pcpu(clock, enable, reset, start, d_datain, i_datain, select_y, i_addr, d_addr, d_dataout, d_we, y); Data_memory data(clock, reset, d_addr, d_dataout, d_we, d_datain); Board_eval eval(clk, y, select_segment, select_bit); endmodule /************************ Instruction memeory module *****************************/ module Instruction_Mem ( input wire clock, reset, input wire[7:0] i_addr, output [15:0] i_datain ); reg[15:0] i_data[255:0]; // 8 bits pc address to get instructions reg[15:0] temp; always@(negedge clock) begin if(!reset) begin i_data[0] |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |