zoukankan      html  css  js  c++  java
  • [计算机组成原理][实验十.R-I-J型指令CPU设计实验总结]

    总算解决一大心头之患了,比想象中容易,通宵两夜,刷完了十个实验,这个实验就是最后的了。感慨颇多。特地写篇总结。

    • 想做一件事,就立马去做把。你会发现没那么困难,往往最大的困难,是心里的困难

    • 培养了HDL(Hardware Description Language)思维,并行串行混合。它先是一个电路,再才是一个程序电路为主,程序为辅,用RTL的思维去思考。

    • 这个实验也不怎么难,就是一个大的模拟题,当年ACM给我良好的代码功底受益颇多。

    • 能硬件级别揣摩CPU的一点点运行方式,但是还有很多疑问,需要看书去解决。

    • 这次的实验只是在心里面扎了一个种子(种子当然很重要啦~),需要看完CSAPP,和硬件/软件接口那两本书才能成长为苍天大树。

    • 实验驱动型+看书解决型,现阶段最好的学习方法了~

    以下是本次实验的数据通路

    module cpu

    module cpu(clk,reset,ALU_OP,inst,rs,rt,rd,rs_data,rt_data,rd_data,ZF,OF,Write_Reg,PC,PC_new,rd_rt_s,W_Addr,imm,W_Data,imm_s,imm_data
    ,ALU_B,rt_imm_s,Mem_Write,M_R_Data,ALU_Data,alu_mem_s,w_r_s,wr_data_s,PC_s,address);
    input wire clk;
    input reset;
    output [2:0] ALU_OP;	//操作符
    output [31:0] inst;		//指令存放
    output [4:0] rs;	//rs地址
    output [4:0] rt;	//rt地址
    output [4:0] rd;	//rd地址
    output [31:0] rs_data;	//rs数据
    output [31:0] rt_data;	//rt数据
    output [31:0] rd_data;	//rd数据
    output [31:0] PC;
    output [31:0] PC_new;
    output ZF;
    output OF;
    output Write_Reg;			//是否写入
    output [31:0] W_Data;
    output rd_rt_s; //控制那个作为目的寄存器
    output [4:0]W_Addr;//目的操作数地址
    output [15:0] imm; //立即数
    output [31:0] imm_data;//被扩展的立即数
    output imm_s;//是否需要扩展
    output rt_imm_s;	//B端选择rt或者是imm
    output [31:0] ALU_B;	//ALU_B端口数据
    output Mem_Write;		//是否写入数据rom
    output [31:0]M_R_Data;//从数据rom读出来的数据
    output [31:0]ALU_Data;//ALU运算出来的结果,根据alu_mem_s选择由M_W_Data或者W_Data来赋值
    output alu_mem_s;//看上面
    output [1:0] w_r_s;
    output [1:0] wr_data_s;
    output [1:0] PC_s;//PC选择器
    output [25:0] address;//地址解析数据
    	//读指令
       ex7 pc (
      .clka(clk), 
      .douta(inst), 
      .rst(reset),
      .PC(PC),
      .PC_new(PC_new),
      .PC_s(PC_s),
      .R_Data_A(rs_data),
      .imm_data(imm_data),
      .address(address)
      //解析指令
      );
      analysis_inst analysis_inst(	
    		.inst(inst),
    		.ALU_OP(ALU_OP),
    		.rs(rs),
    		.rt(rt),
    		.rd(rd),
    		.Write_Reg(Write_Reg),
    		.imm(imm),
    		.rd_rt_s(rd_rt_s),
    		.imm_s(imm_s),
    		.rt_imm_s(rt_imm_s),
    		.Mem_Write(Mem_Write),
    		.alu_mem_s(alu_mem_s),
    		.address(address),
    		.w_r_s(w_r_s),
    		.wr_data_s(wr_data_s),
    		.PC_s(PC_s),
    		.ZF(ZF)
        );
    	//读取源操作数的值:
    	assign W_Addr = (w_r_s[1])?5'b11111:((w_r_s[0])?rt:rd);
    	assign imm_data = (imm_s)?{{16{imm[15]}},imm}:{{16{1'b0}},imm};
    	
    	reg1 Reg(
    		.R_Addr_A(rs),
    		.R_Addr_B(rt),
    		.Clk(clk),
    		.W_Addr(W_Addr),
    		.W_Data(W_Data),	
    		.R_Data_A(rs_data),
    		.R_Data_B(rt_data),
    		.Reset(reset),
    		.Write_Reg(Write_Reg) //不写入
    	);
    	assign ALU_B=(rt_imm_s)?imm_data:rt_data;
    	//对源操作数运算,存于目的操作数
    	ex3 ALU(
    	.ALU_OP(ALU_OP),
    	.A(rs_data),
    	.B(ALU_B),
    	.F(ALU_Data),
    	.ZF(ZF),
    	.OF(OF)
    	);
    //----
    wire clk_temp;
    wire d_outn;
    reg  d_out=0;
    assign clk_temp = clk ^ d_out ;
    assign d_outn = ~d_out ;
    //----
    always@(posedge clk_temp)
    begin
      d_out <= d_outn ; 
    end
    	//数据存储器
    	Data_Rom Datarom (
      .clka(clk_temp), // input clka
      .wea(Mem_Write), // input [0 : 0] wea
      .addra(ALU_Data[5:0]), // input [5 : 0] addra
      .dina(rt_data), // input [31 : 0] dina
      .douta(M_R_Data) // output [31 : 0] douta
    );
    	assign W_Data = (wr_data_s[1])?PC_new:(wr_data_s[0]?M_R_Data:ALU_Data);
    
    endmodule
    

    module pc

    `timescale 1ns / 1ps
    //////////////////////////////////////////////////////////////////////////////////
    // Company: 
    // Engineer: 
    // 
    // Create Date:    03:28:40 05/17/2016 
    // Design Name: 
    // Module Name:    ex7 
    // Project Name: 
    // Target Devices: 
    // Tool versions: 
    // Description: 
    //
    // Dependencies: 
    //
    // Revision: 
    // Revision 0.01 - File Created
    // Additional Comments: 
    //
    //////////////////////////////////////////////////////////////////////////////////
    module ex7(clka,douta,rst,PC,PC_new,PC_s,R_Data_A,imm_data,address
        );
    input rst;
    input clka;
    input [1:0] PC_s;
    output  wire [31:0] douta;
    output  reg [31:0] PC;
    output   [31:0] PC_new;
    input   [31:0] R_Data_A;
    input   [31:0] imm_data;
    input   [25:0] address;
    
    wire [31:0]dina;
    reg [0:0] wea=0;
    assign PC_new=PC+4;
    	
    ex77 regrom (
      .clka(clka), // input clka
      .wea(wea), // input [0 : 0] wea
      .addra(PC[7:2]), // input [5 : 0] addra
      .dina(dina), // input [31 : 0] dina
      .douta(douta) // output [31 : 0] douta
    );
    always@(posedge rst or negedge clka)
    begin 
    	if(rst)
    	   PC<=32'h00000000;
    	else 
    		begin
    			case(PC_s)
    				2'b00: PC<=PC_new;
    				2'b01: PC<=R_Data_A;
    				2'b10: PC<=PC_new+(imm_data<<2);
    				2'b11: PC<={PC_new[31:28],address,2'b00};
    			endcase
    		end
    end
    endmodule
    

    module analysis_inst

    `timescale 1ns / 1ps
    //////////////////////////////////////////////////////////////////////////////////
    // Company: 
    // Engineer: 
    // 
    // Create Date:    07:31:58 05/17/2016 
    // Design Name: 
    // Module Name:    analysis_inst 
    // Project Name: 
    // Target Devices: 
    // Tool versions: 
    // Description: 
    //
    // Dependencies: 
    //
    // Revision: 
    // Revision 0.01 - File Created
    // Additional Comments: 
    //
    //////////////////////////////////////////////////////////////////////////////////
    module analysis_inst(
    inst,ALU_OP,rs,rt,rd,Write_Reg,imm,rd_rt_s,imm_s,rt_imm_s,Mem_Write,alu_mem_s,address,w_r_s,wr_data_s,PC_s,ZF
        );
    input [31:0] inst;
    output reg [2:0] ALU_OP;
    output reg [4:0] rs;
    output reg [4:0] rt;
    output reg [4:0] rd;
    output reg Write_Reg;
    output reg [15:0] imm;
    output reg rd_rt_s;
    output reg imm_s;
    output reg rt_imm_s;
    output reg Mem_Write;
    output reg alu_mem_s;
    output reg [25:0] address;
    output reg [1:0] w_r_s;
    output reg [1:0] wr_data_s;
    output reg [1:0] PC_s;
    input  ZF;
    always@(*)
    begin
    //--------------------处理R型指令----------------------
     if(inst[31:26]==6'b000000)	//判断是否为R型
    	begin
    	  rd=inst[15:11];		//rd
    	  rt=inst[20:16];		//rt
    	  rs=inst[25:21];		//rs
    	  w_r_s=2'b00;
    	  imm_s=0;//此处无所谓
    	  wr_data_s=2'b00;
    	  // alu_mem_s=0;//此处废弃不用,被wr_data_s替代
    	  Mem_Write=0;//是否写入数据存储器
    	  //rd_rt_s=0;//rd作为目的存储器//此处废弃不用吧被w_r_s替代
    	  rt_imm_s=0;//rt作为源操作数
    	  case(inst[5:0])	//映射对应的ALU
    	    6'b100000:begin ALU_OP=3'B100; Write_Reg=1;PC_s=2'b00;end
    		 6'b100010:begin ALU_OP=3'B101; Write_Reg=1;PC_s=2'b00;end
    		 6'b100100:begin ALU_OP=3'B000; Write_Reg=1;PC_s=2'b00;end
    		 6'b100101:begin ALU_OP=3'B001; Write_Reg=1;PC_s=2'b00;end
    		 6'b100110:begin ALU_OP=3'B010; Write_Reg=1;PC_s=2'b00;end
    		 6'b100111:begin ALU_OP=3'B011; Write_Reg=1;PC_s=2'b00;end
    		 6'b101011:begin ALU_OP=3'B110; Write_Reg=1;PC_s=2'b00;end 
    	 	 6'b000100:begin ALU_OP=3'B111; Write_Reg=1;PC_s=2'b00;end 
    		 6'b001000:begin ALU_OP=3'B100; Write_Reg=0;PC_s=2'b01;end
    		endcase
    	 end
    //------------------处理I型立即寻址指令------------------------	 
      if(inst[31:29]==3'b001)
    	begin
    	  imm=inst[15:0];
    	  rt=inst[20:16];		//rt
    	  rs=inst[25:21];		//rs
    	  Mem_Write=0;//是否写入数据存储器
    	  rd_rt_s=1;//rt作为目的存储器
    	  rt_imm_s=1;//imm作为源操作数
    	 // alu_mem_s=0;//以alu结果输出
    	  w_r_s=2'b01;
    	  Write_Reg=1;
    	  wr_data_s=2'b00;
    	  PC_s=2'b00;
    	  //判断属于那条指令
    	  case(inst[31:26])
    	  6'b001000: begin imm_s=1; ALU_OP=3'B100;end
    	  6'b001100: begin imm_s=0; ALU_OP=3'B000;end
    	  6'b001110: begin imm_s=0; ALU_OP=3'B010;end
    	  6'b001011: begin imm_s=0; ALU_OP=3'B110;end
    	  endcase
    	end
    //----------------处理I型取数/存数指令------------------
      if(inst[31:30]==2'b10&&inst[28:26]==3'b011)
    	begin
    	  imm=inst[15:0];
    	  rt=inst[20:16];		//rt
    	  rs=inst[25:21];		//rs
    	  rd_rt_s=1;//rt作为目的存储器
    	  rt_imm_s=1;//imm作为源操作数
    	  imm_s=1;
    	  w_r_s=2'b01;
    	  wr_data_s=2'b01;
    	  PC_s=2'b00;
    	  //判断属于那条指令
    	  //读取数据时,以mem输出的数据写入,所以alu_mem_s=1;
    	  case(inst[31:26])
    	  6'b100011: begin alu_mem_s=1; Mem_Write=0;Write_Reg=1;ALU_OP=3'B100;end
    	  6'b101011: begin  Mem_Write=1;Write_Reg=0;ALU_OP=3'B100;end
    	  endcase
    	end
    //----------------处理I型跳转指令------------------------
    	if(inst[31:27]==5'b00010)
    	 begin
    	  imm=inst[15:0];
    	  rt=inst[20:16];		//rt
    	  rs=inst[25:21];		//rs
    	 case(inst[31:26])
    	 6'b000100:begin rt_imm_s=0;ALU_OP=3'b101;Write_Reg=0;Mem_Write=0;PC_s=(ZF?2'b10:2'b00); end
    	 6'b000101:begin rt_imm_s=0;ALU_OP=3'b101;Write_Reg=0;Mem_Write=0;PC_s=(ZF?2'b00:2'b10); end
    	 endcase
    	 end
    //----------------处理J型跳转指令-------------------------
    	if(inst[31:27]==5'b00001)
    	 begin
    	 address=inst[25:0];
    	 case(inst[31:26])
    	 6'b000010:begin w_r_s=2'b00;Write_Reg=0;Mem_Write=0;PC_s=2'b11; end
    	 6'b000011:begin w_r_s=2'b10;wr_data_s=2'b10;Write_Reg=1;Mem_Write=0;PC_s=2'b11; end
    	 endcase
    	 end
    end
    endmodule
    

    module Reg

    `timescale 1ns / 1ps
    //////////////////////////////////////////////////////////////////////////////////
    // Company: 
    // Engineer: 
    // 
    // Create Date:    00:34:10 05/17/2016 
    // Design Name: 
    // Module Name:    reg1 
    // Project Name: 
    // Target Devices: 
    // Tool versions: 
    // Description: 
    //
    // Dependencies: 
    //
    // Revision: 
    // Revision 0.01 - File Created
    // Additional Comments: 
    //
    //////////////////////////////////////////////////////////////////////////////////
    module reg1(R_Addr_A,R_Addr_B,Clk,W_Addr,W_Data,R_Data_A,R_Data_B,Reset,Write_Reg
    );
    input Clk,Reset;
    input wire Write_Reg;
    input wire[4:0] R_Addr_A;
    input wire[4:0] W_Addr;
    input wire[4:0] R_Addr_B;
    input wire[31:0] W_Data;
    reg[31:0] REG_Files[31:0];
    output wire[31:0] R_Data_A;
    output wire[31:0] R_Data_B;
    
    integer i=0;
    always @(posedge Clk or posedge Reset)		//下降沿存储
    begin
    	if(Reset)	//初始化
    	begin
    		for(i=0;i<=31;i=i+1)
    		REG_Files[i]<=32'h00000000;
    	end
    	else
    		begin
    			if(Write_Reg)
    			REG_Files[W_Addr]<=W_Data;
    		end
    end
    	 assign R_Data_A=REG_Files[R_Addr_A];
        assign R_Data_B=REG_Files[R_Addr_B];
    endmodule
    

    module ALU

    `timescale 1ns / 1ps
    //////////////////////////////////////////////////////////////////////////////////
    // Company: 
    // Engineer: 
    // 
    // Create Date:    14:06:30 03/31/2016 
    // Design Name: 
    // Module Name:    ex3 
    // Project Name: 
    // Target Devices: 
    // Tool versions: 
    // Description: 
    //
    // Dependencies: 
    //
    // Revision: 
    // Revision 0.01 - File Created
    // Additional Comments: 
    //
    //////////////////////////////////////////////////////////////////////////////////
    module ex3(ALU_OP,A,B,F,ZF,OF
    );
    input[2:0] ALU_OP;
    input[31:0] A,B;
    output reg [31:0] F;
    output reg ZF,OF;
    reg C32,C31;
    reg [7:0]i;
    always@(*)
    begin
    
    case(ALU_OP)
    	3'b000:F=A&B;
    	3'b001:F=A|B;
    	3'b010:F=A^B;
    	3'b011:F=~(A|B);
    	3'b100:begin{C32,F}=A+B;OF=C32^A[31]^B[31]^F[31];end
    	3'b101:begin{C32,F}=A-B;OF=C32^A[31]^B[31]^F[31];end
    	3'b110:begin if(A<B)
    				  F=1;
    			   else
    				  F=0;
    		    end
    	3'b111:F=B<<A;
    	default: begin  end
    	endcase
    
    	ZF=((F==32'h00000000)?1:0);		
    end
    endmodule
  • 相关阅读:
    是什么造成了数据库的卡顿
    机器学习笔记(六) ---- 支持向量机(SVM)
    机器学习笔记(五)---- 决策树
    了解 MongoDB 看这一篇就够了【华为云分享】
    王晶:华为云OCR文字识别服务技术实践、底层框架及应用场景 | AI ProCon 2019
    【HUAWEI Mate30】抽奖啦!华为IoT新福利上线!
    高性能Web动画和渲染原理系列(2)——渲染管线和CPU渲染
    【华为云社区】悟一下动态规划
    理解递归与动态规划
    Laravel 文件上传失败的问题 error 7
  • 原文地址:https://www.cnblogs.com/zy691357966/p/5504764.html
Copyright © 2011-2022 走看看