[计算机组成原理][R-I-J型指令CPU设计实验总结]

来源:互联网 发布:pkpm网络计划软件 编辑:程序博客网 时间:2024/05/17 09:33

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

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

  • 培养了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或者是immoutput [31:0] ALU_B;    //ALU_B端口数据output Mem_Write;       //是否写入数据romoutput [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        endendendmodule

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     endendendmodule

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;        endend     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@(*)begincase(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);     endendmodule
0 0