【verilog】多周期MIPS CPU设计

一、    实验要求

设计并实现一个多周期MIPS CPU,并满足如下要求:

1)仅允许使用一个存储器

2)实现六条指令:addi、add、lw、sw、bgtz、j

3)对给予的斐波那契数列例程进行测试

 

二、    实验原理

1)数据通路:

上图中不包含j指令的数据通路,添加后如下:

2)有限状态机(FSM)——状态图

 

 

三、    实验内容

1.生成IP核

为了使编码简单,这里的ram采用的是异步读,同步写,宽度32bit,深度为64.

     (模块端口)

 

2.主要代码分析

 
module top(

input clk,

input reset,

output [31:0] pc_in,

output [31:0] pc_out,

output pc_write

    );

 

wire [2:0]alu_op;

wire [1:0]pc_src;

wire alu_src_a;

wire [1:0]alu_src_b;

wire mem_toreg;

wire reg_write;

wire reg_dst;

wire [4:0]rd;

wire [31:0]data_out;

wire [31:0]data_out1;

wire [31:0]data_out2;

wire [31:0]data_out_a;

wire [31:0]data_out_b;

wire [31:0]data_out_out;

wire [31:0]alu_out;

wire [31:0]alu_out_out;

wire [31:0]data_write;

wire [31:0]src_a;

wire [31:0]src_b;

wire [31:0]imm;

wire mem_write;

wire ir_write;

wire [31:0]inst;

wire [31:0]addr;

wire branch_2;

wire pc_write_2;

 

 

branchand band(branch,data_out_a,branch_2);

 

branchor bor(branch_2,pc_write,pc_write_2);

        

pc pc(clk, pc_in, pc_write_2, reset, pc_out);

 

dataselect_32_bitaddrmux(pc_out,alu_out_out,i_or_d,addr);

 

ram ram(addr,data_out2,clk,mem_write,data_out);

 

ir ins(data_out,clk,ir_write,inst);

 

dataselect_5_bitregdst(inst[20:16],inst[15:11],reg_dst,rd);

 

data d(data_out, clk,data_out_out);

 

dataselect_32_bitdatamux(alu_out,data_out_out,mem_toreg,data_write);

 

regfilere(inst[25:21],inst[20:16],data_write,rd,reg_write,clk,data_out1, data_out2);

 

ab ab(data_out1,data_out2,clk,data_out_a,data_out_b);

 

dataselect_32_bitA(pc_out,data_out_a,alu_src_a,src_a);

 

signextension im(inst[15:0],imm);

 

dataselect_32_bit_4dataB(data_out_b,32'b1,imm,imm,alu_src_b,src_b);

 

alu a(src_a,src_b,alu_op,alu_out);

 

data aluout(alu_out,clk,alu_out_out);

 

dataselect_32_bit_3data pcsrc(alu_out,alu_out_out,inst[25:0],pc_src, pc_in);

 

controlunitcon(inst[31:26],reset,5'b0,clk,pc_write,branch,pc_src,alu_op,alu_src_a,alu_src_b,reg_write,i_or_d,ir_write,mem_write,mem_toreg,reg_dst);

 

endmodule

 

********************************************************************************************

 

modulecontrolunit(    //控制模块,用于译码产生控制信号,包含两个子模块

  input [5:0] opcode,

  input reset,

  input [5:0] funct,    //本实验只考虑add所以暂时用不到这个字段

  input clk,

  output pc_write,

  output branch,

  output [1:0]pc_src,

  output [2:0] alu_op,

  output alu_src_a,

  output [1:0] alu_src_b,

  output reg_write,

  output i_or_d,

  output ir_write,

  output mem_write,

  output mem_toreg,

  output reg_dst

   );

 

reg[3:0]now_state = 4'b0;      //当前状态

wire[3:0]next_state;                   //下一个状态

 

always@(posedgeclk)

       if(~reset)begin  now_state = 5'b0; end

       else

       begin

              now_state = next_state;             //根据子模块1的运算结果进行状态转换

       end

 

nextstatenext(now_state,opcode,next_state);//子模块1,用于运算下一个状态

control_outputout(                                   //子模块2,用于根据当前状态进行输出

                                          opcode,

                                          now_state,

                                          pc_write,

                                 branch,

                                          pc_src,

                                          alu_op,

                                 alu_src_a,

                                 alu_src_b,

                                 reg_write,

                                          i_or_d,

                                          ir_write,

                                          mem_write,

                                          mem_toreg,

                                          reg_dst);

endmodule

 

********************************************************************************************

 

 

module nextstate(i_state,opcode, next_state);

   input [3:0]i_state;

   input [5:0]opcode;

   output reg[3:0]next_state;

        

   parameter [3:0] s0 = 4'd0,

                             s1 = 4'd1,

                                            s2 = 4'd2,

                                            s3 = 4'd3,

                                            s4 = 4'd4,

                                            s5 = 4'd5,

                                            s6 = 4'd6,

                                            s7 = 4'd7,

                                            s8 = 4'd8,

                                            s9 = 4'd9,

                                            s10 = 4'd10,

                                            s11 = 4'd11;

                                           

                                           

   always @(*) 

      

              begin

       case (i_state)

               

           s0: next_state = s1;

           s1:

                                   begin

                case (opcode)

                    6'b000000: next_state=  s6;           //add

                                            6'b001000: next_state =  s9;    //addi

                                            6'b100011: next_state =  s2;   //lw

                                            6'b101011: next_state =  s2;    //sw

                                            6'b000010: next_state =  s11; //jump

                                            6'b000111: next_state =  s8;  //bgtz

                endcase

                                   end

                                  

           s2:

                                   begin

                case (opcode)

                                            6'b100011: next_state =  s3;        //lw

                                            6'b101011: next_state =  s5;     //sw                             

                endcase

                                   end

           s3: next_state = s4;

           s4: next_state = s0;

           s5: next_state = s0;

           s6: next_state = s7;

           s7: next_state = s0;

                            s8:next_state = s0;

                            s9:next_state = s10;

                            s10:next_state = s0;

                            s11:next_state = s0;

       endcase

    end

endmodule

 

 

 

********************************************************************************************

 

module control_output(                           //根据当前state进行输出

  input[5:0] opcode,

  input[3:0] state,

 

 output reg pc_write,

 output reg branch,

 output reg [1:0]pc_src,

 output reg [2:0] alu_op,

 output reg alu_src_a,

 output reg [1:0]alu_src_b,

  outputreg reg_write,

 output reg i_or_d,

 output reg ir_write,

 output reg mem_write,

 output reg mem_toreg,

 output reg reg_dst

    );

 

 

parameter [3:0] s0 = 4'd0,

                s1 = 4'd1,

                                    s2 = 4'd2,

                                    s3 = 4'd3,

                                    s4 = 4'd4,

                                    s5 = 4'd5,

                                    s6 = 4'd6,

                                    s7 = 4'd7,

                                    s8 = 4'd8,

                                    s9 = 4'd9,

                                    s10 = 4'd10,

                                    s11 = 4'd11;

 

 

always @(state)

              begin

              case(state)

                     s0:

                            begin

                             pc_write=                    1;

                           branch=                      0;

                        pc_src=               2'b00;

                        alu_op=               2'b01;    //alu的操作码与ppt给定的不同

                                                                        //因为alu模块编写的不同进行了调整

                        alu_src_a=             0;

                        alu_src_b=             2'b01;

                        reg_write=                    0;

                        i_or_d=               0;

                        ir_write=              1;

                        mem_write=           0;

                        mem_toreg=           0;

                        reg_dst=              0;

                            end

                     s1:

                            begin

                             pc_write=                    0;

                        alu_src_b=            2'b11;

                        ir_write=             0;

                            end

                     s2:

                            begin

                        alu_op=            2'b01;

                        alu_src_a=            1;

                        alu_src_b=       2'b10;

                            end

                     s3:

                            begin

                        i_or_d=               1;

                            end

                     s4:

                            begin

                        reg_write=                    1;

                        mem_toreg=          1;

                        reg_dst=              0;

                            end

                     s5:

                            begin

                        i_or_d=               1;

                        mem_write=           1;

                             //pc_write =          1;

                            end

                     s6:

                            begin

                        alu_op=              2'b01;

                        alu_src_a=            1;

                        alu_src_b=            2'b00;

                            end

                     s7:

                            begin

                        reg_write=                    1;

                        mem_toreg=           0;

                        reg_dst=              1;

                            end

                     s8:

                            begin

                           branch=                      1;

                        pc_src=                 2'b01;

                        alu_op=                2'b10;

                        alu_src_a=              1;

                        alu_src_b=               2'b10;

                            end

                     s9:

                            begin

                        alu_op=               2'b01;

                        alu_src_a=            1;

                        alu_src_b=            2'b10;

                            end

                     s10:

                            begin

                        reg_write=                    1;

                        mem_toreg=           0;

                        reg_dst=               0;

                            end

                     s11:

                            begin

                             pc_write=                    1;

                        pc_src=                2'b10;

                            end

      endcase

    end

endmodule

 

 

 

********************************************************************************************

 

其余模块较为简单或者见之前实验报告,此处略去

 

3.coe文件编写

Coe文件中存储了待运行的代码以及相关的数据,这里根据本人的设计做了响应的修改

下面是coe文件的具体内容,以及对应产生的内存数据:

 

 

 

4.仿真

 

波形图看起来比较不直观,这里主要观察指令以及状态的跳转是否正确:

 

确认指令执行无误后,观察内存里的内容,如下(十进制):

 

四、    实验分析和总结

本实验于单周期的cpu相比,数据通路上发生了一些较为明显的变化,首先指令和数据不再分开存放,其次增加了一定数量的寄存器存储关键数据,这是由多周期指令特性决定的。

然后,多周期cpu的设计运用了有限状态机的思想,这在单周期cpu里是没有体现的,每个指令再不同的时钟周期里,其控制信号完全不同,所以需要状态机来控制状态的条状,并且根据不同指令的不同状态来决定控制信号的输出。

 

 

 

 

  • 6
    点赞
  • 74
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
### 回答1: Verilog周期MIPS CPU设计是一种基于MIPS指令集架构的CPU设计,采用单周期的执行方式,包括取指、译码、执行、访存和写回等阶段。该设计需要实现MIPS指令集中的各种指令,包括算术运算、逻辑运算、分支跳转、访存等操作。同时,还需要考虑CPU的时序控制、数据通路设计、寄存器堆、ALU等模块的实现。该设计需要对Verilog语言有一定的掌握和理解,同时需要对计算机组成原理和数字电路等相关知识有一定的了解。 ### 回答2: Verilog周期MIPS CPU设计,是一种基于MIPS结构的中央处理器的设计,使用Verilog硬件描述语言实现。MIPS架构是一种经典的RISC架构,广泛应用于嵌入式系统中。 MIPS CPU设计可以分为指令集架构、流水线结构以及单周期结构三个方面。在单周期结构中,每个指令都需要一个时钟周期完成。整个CPU由多个单元组成,包括PC计数器、指令存储器、寄存器组、ALU等。 具体来说,Verilog周期MIPS CPU设计需要考虑以下几个方面: 1. 指令存储器的设计。指令存储器是存储指令的地方,需要按照MIPS架构格式存储指令,同时需要设计好指令计数器(PC)。 2. 控制器的设计。控制器是CPU的核心部件之一,用于根据指令控制各个单元的操作。在单周期CPU中,控制器需要根据指令的类型和操作码生成不同的控制信号。 3. 寄存器组的设计。寄存器组是一个非常重要的部分,需要提供32个通用寄存器,同时需要根据指令设计好数据通路,实现寄存器之间的数据传输。 4. ALU的设计。ALU是完成算术和逻辑运算的核心部件,需要支持基本的加减乘除、移位、与或非等操作。 5. 数据通路的设计。数据通路将各个单元连接在一起,实现了数据的传输和操作。需要根据指令设计好数据通路,保证指令的正确执行。 在完成以上设计后,需要进行仿真和验证。使用Verilog语言的仿真工具进行验证,确保CPU的性能和正确性。最后,完成物理实现后将MIPS CPU与外设进行连接,实现系统的最终功能。 总之,Verilog周期MIPS CPU设计是一项复杂而重要的工程,需要深入理解MIPS架构,同时也需要综合运用Verilog的各种知识和技术。它的设计和实现对于嵌入式系统的发展有着非常重要的意义。 ### 回答3: Verilog周期MIPS CPU设计是基于MIPS架构的单周期CPU设计,这种CPU可以实现多种寄存器、指令和内存等常用的微处理器功能。MIPS CPU在计算机硬件领域应用十分广泛。 Verilog周期MIPS CPU设计可以分为数据通路和控制器两个部分。数据通路包括ALU、存储器、寄存器和地址传输等,控制器则负责产生各种信号来控制CPU的各种行为。 MIPS CPU采用大量寄存器,通过控制器模块控制多路选择器的不同输入,来实现数据传输和指令执行等操作。寄存器制作时需要注意,尽量将读操作和写操作明确分开,避免两者发生竞争引起的问题。 指令的执行则需要根据不同指令的性质进行设置。CPU设计了多路选择器,用于选择正确的指令操作数和操作。再通过ALU进行指令计算,最后将执行结果写回寄存器或者内存中。 总体来说,Verilog周期MIPS CPU设计需要对MIPS指令集进行深入了解,清楚每条指令的功能和使用方法。然后根据逻辑设计知识,使用Verilog语言编写代码实现具体功能。在设计过程中,要注意各个模块之间的衔接,确保数据和控制信号的流畅处理。 值得注意的是,完成Verilog周期MIPS CPU设计只是整个设计的开始。接下来需要进行仿真,调试,并将设计映射到硅片上,进行硬件验证和测试。只有这样才能让设计变成可用的CPU,为人们带来实际应用带来便利。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值