verilog实现的五级流水简易CPU(带板极验证)

您所在的位置:网站首页 五级流水线cpu设计方案 verilog实现的五级流水简易CPU(带板极验证)

verilog实现的五级流水简易CPU(带板极验证)

2024-07-13 07:17| 来源: 网络整理| 查看: 265

 实现一个简易的五级流水的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