打印
[RISC-V MCU 创新应用比赛]

从零开始设计RISC-V处理器——单周期处理器的设计

[复制链接]
楼主: 9dome猫
手机看帖
扫描二维码
随时随地手机跟帖
41
9dome猫|  楼主 | 2022-6-28 15:13 | 只看该作者 |只看大图 回帖奖励 |倒序浏览
代码如下:
module datapath(
        input         clk,
        input   rst_n,
        input   [31:0]instr,


        input   MemtoReg,
        input   ALUSrc,
        input   RegWrite,
        input   lui,
        input   U_type,
        input   jal,
        input   jalr,
        input   beq,
        input   bne,
        input   blt,
        input   bge,
        input   bltu,
        input   bgeu,
        input   [3:0]ALUctl,
       
        input [31:0]Rd_mem_data,
        output  [7:0]rom_addr,
        output [31:0]Wr_mem_data,
        output [31:0]ALU_result,
        output [6:0]opcode,
        output [2:0]func3,
        output func7
       
       
    );
       
       
       
       
       
       
        wire [4:0]Rs1;
        wire [4:0]Rs2;
        wire [4:0]Rd;
        wire [31:0]imme;
       
        wire [31:0] Wr_reg_data;
        wire [31:0] Rd_data1;
        wire [31:0] Rd_data2;
       
        wire zero;
       
        wire [31:0]pc_order;
        wire [31:0]pc_jump;
       
        wire   [31:0]pc_new;
        wire [31:0]pc_out;
       
        wire jump_flag;
       
        wire [31:0]ALU_DB;
        wire [31:0]WB_data;
       
        wire reg_sel;
        wire [31:0]Wr_reg_data1;
        wire [31:0]Wr_reg_data2;
        wire [31:0]pc_jump_order;
        wire [31:0]pc_jalr;
       
       
        assign reg_sel=jal | jalr ;
        assign Wr_mem_data=Rd_data2;
        assign rom_addr=pc_out[9:2];
        assign pc_jalr={ALU_result[31:1],1'b0};
       
        pc_reg pc_reg_inst (
    .clk(clk),
    .rst_n(rst_n),
    .pc_new(pc_new),
    .pc_out(pc_out)
    );

       
        instr_decode instr_decode_inst (
    .instr(instr),
    .opcode(opcode),
    .func3(func3),
    .func7(func7),
    .Rs1(Rs1),
    .Rs2(Rs2),
    .Rd(Rd),
    .imme(imme)
    );
       
    registers registers_inst (
    .clk(clk),
    .W_en(RegWrite),
    .Rs1(Rs1),
    .Rs2(Rs2),
    .Rd(Rd),
    .Wr_data(Wr_reg_data),
    .Rd_data1(Rd_data1),
    .Rd_data2(Rd_data2)
    );

       
        alu alu_inst (
    .ALU_DA(Rd_data1),
    .ALU_DB(ALU_DB),
    .ALU_CTL(ALUctl),
    .ALU_ZERO(zero),
    .ALU_OverFlow(),
    .ALU_DC(ALU_result)
    );

        branch_judge branch_judge_inst (
    .beq(beq),
    .bne(bne),
    .blt(blt),
    .bge(bge),
    .bltu(bltu),
    .bgeu(bgeu),
    .jal(jal),
    .jalr(jalr),
    .zero(zero),
    .ALU_result(ALU_result),
    .jump_flag(jump_flag)
    );

       

       
//pc+4       
        cla_adder32 pc_adder_4 (
    .A(pc_out),
    .B(32'd4),
    .cin(1'd0),
    .result(pc_order),
    .cout()
    );
       
/pc+imme
        cla_adder32 pc_adder_imme (
    .A(pc_out),
    .B(imme),
    .cin(1'd0),
    .result(pc_jump),
    .cout()
    );
       

/pc_sel
        mux pc_mux (
    .data1(pc_jump),
    .data2(pc_order),
    .sel(jump_flag),
    .dout(pc_jump_order)
    );
///pc_jalr
        mux pc_jalr_mux (
    .data1(pc_jalr),
    .data2(pc_jump_order),
    .sel(jalr),
    .dout(pc_new)
    );

       
       
ALUdata_sel       
        mux ALU_data_mux (
    .data1(imme),
    .data2(Rd_data2),
    .sel(ALUSrc),
    .dout(ALU_DB)
    );
       
       
/ALU_result or datamem       
        mux WB_data_mux (
    .data1(Rd_mem_data),
    .data2(ALU_result),
    .sel(MemtoReg),
    .dout(WB_data)
    );
       
       
Wr_data_sel
        mux jalr_mux (
    .data1(pc_order),
    .data2(WB_data),
    .sel(reg_sel),
    .dout(Wr_reg_data2)
    );
       
        mux lui_mux (
    .data1(imme),
    .data2(pc_jump),
    .sel(lui),
    .dout(Wr_reg_data1)
    );
       
        mux Wr_reg_mux (
    .data1(Wr_reg_data1),
    .data2(Wr_reg_data2),
    .sel(U_type),
    .dout(Wr_reg_data)
    );

endmodule

使用特权

评论回复
42
9dome猫|  楼主 | 2022-6-28 15:14 | 只看该作者
四.控制器
1.主控制器
由于不同类型的指令所经过的数据通路不同,所以需要有控制信号控制数据通路,使得数据经过正确的通路,得到正确的运算结果。

使用特权

评论回复
43
9dome猫|  楼主 | 2022-6-28 15:14 | 只看该作者
本设计将控制器分为两级控制,主控制器产生大部分的控制信号,子控制器是ALU控制器,产生控制ALU进行正确运算的信号。

使用特权

评论回复
44
9dome猫|  楼主 | 2022-6-28 15:15 | 只看该作者
模块的输入输出端口定义如下:

使用特权

评论回复
45
9dome猫|  楼主 | 2022-6-28 15:16 | 只看该作者
代码如下:
module main_control(
        opcode,
        func3,
        MemRead,
        MemtoReg,
        ALUop,
        MemWrite,
        ALUSrc,
        RegWrite,
        lui,
        U_type,
        jal,
        jalr,
        beq,
        bne,
        blt,
        bge,
        bltu,
        bgeu,
        RW_type
    );
        input [6:0]opcode;
        input [2:0]func3;
       
        output   MemRead;
        output   MemtoReg;
        output   [1:0]ALUop;
        output   MemWrite;
        output   ALUSrc;
        output   RegWrite;
        output   lui;
        output   U_type;
        output   jal;
        output   jalr;
        output   beq;
        output   bne;
        output   blt;
        output   bge;
        output   bltu;
        output   bgeu;
        output   [2:0]RW_type;
       
        wire branch;
        wire R_type;
        wire I_type;
        wire load;
        wire store;
        wire lui;
        wire auipc;

       
        assign branch=(opcode==`B_type)?1'b1:1'b0;
        assign R_type=(opcode==`R_type)?1'b1:1'b0;
        assign I_type=(opcode==`I_type)?1'b1:1'b0;
        assign U_type=(lui | auipc)? 1'b1:1'b0;
        assign load=(opcode==`load)?1'b1:1'b0;
        assign store=(opcode==`store)?1'b1:1'b0;
       
        assign jal=(opcode==`jal)?1'b1:1'b0;
        assign jalr=(opcode==`jalr)?1'b1:1'b0;
        assign lui=(opcode==`lui)?1'b1:1'b0;
        assign auipc=(opcode==`auipc)?1'b1:1'b0;
        assign beq= branch & (func3==3'b000);
        assign bne= branch & (func3==3'b001);
        assign blt= branch & (func3==3'b100);
        assign bge= branch & (func3==3'b101);
        assign bltu= branch & (func3==3'b110);
        assign bgeu= branch & (func3==3'b111);
        assign RW_type=func3;
       
       
        enable
        assign MemRead= load;
        assign MemWrite= store;
        assign RegWrite= jal| jalr | load | I_type |R_type | U_type;
       
        MUX
        assign ALUSrc=load | store |I_type | jalr;  //select imme
        assign MemtoReg= load;  //select datamemory data
       
        ALUop
        assign ALUop[1]= R_type|branch; //R 10 I 01 B 11 add 00
        assign ALUop[0]= I_type|branch;
       
       
endmodule

使用特权

评论回复
46
9dome猫|  楼主 | 2022-6-28 15:16 | 只看该作者
2.子控制器
子控制器根据主控制器产生的ALUop信号,结合func3和func7信号来产生ALUctl信号。

ALUop信号的设置如下:

使用特权

评论回复
47
9dome猫|  楼主 | 2022-6-28 15:17 | 只看该作者
ALUctl信号设置如下:

使用特权

评论回复
48
9dome猫|  楼主 | 2022-6-28 15:18 | 只看该作者
模块的输入输出端口定义如下:

使用特权

评论回复
49
9dome猫|  楼主 | 2022-6-28 15:19 | 只看该作者
代码如下:
module alu_control(
        ALUop,
        func3,
        func7,
        ALUctl
    );
        input [1:0]ALUop;
        input [2:0]func3;
        input func7;
        output [3:0]ALUctl;
       
        wire [3:0]branchop;
        reg  [3:0]RIop;
       
       
       
        assign branchop=(func3[2] & func3[1])? `SLTU : (func3[2] ^ func3[1])? `SLT : `SUB;
       
        always@(*)
        begin
                case(func3)
                        3'b000: if(ALUop[1] & func7) //R
                                        RIop=`SUB;
                                        else                 //I
                                        RIop=`ADD;
                        3'b001: RIop=`SLL;
                        3'b010: RIop=`SLT;
                        3'b011: RIop=`SLTU;
                        3'b100: RIop=`XOR;
                        3'b101: if(func7)
                                        RIop=`SRA;
                                        else
                                        RIop=`SRL;
                        3'b110: RIop=`OR;
                        3'b111: RIop=`AND;
                        default:RIop=`ADD;
                endcase
        end
       
        assign ALUctl=(ALUop[1]^ALUop[0])? RIop:(ALUop[1]&ALUop[0])?branchop:`ADD;

endmodule

使用特权

评论回复
50
9dome猫|  楼主 | 2022-6-28 15:19 | 只看该作者
3.控制器
将主控制模块和子控制模块进行实例化,得到控制模块。
代码如下:
`include "define.v"
module control(
        opcode,
        func3,
        func7,
        MemRead,
        MemtoReg,
        MemWrite,
        ALUSrc,
        RegWrite,
        lui,
        U_type,
        jal,
        jalr,
        beq,
        bne,
        blt,
        bge,
        bltu,
        bgeu,
        RW_type,
        ALUctl

    );
        input          [6:0]opcode;
        input          [2:0]func3;
        input          func7;
        output   MemRead;
        output   MemtoReg;
        output   MemWrite;
        output   ALUSrc;
        output   RegWrite;
        output   lui;
        output   U_type;
        output   jal;
        output   jalr;
        output   beq;
        output   bne;
        output   blt;
        output   bge;
        output   bltu;
        output   bgeu;
        output   [2:0]RW_type;
        output   [3:0]ALUctl;
       
        wire [1:0]ALUop;
       
        main_control main_control_inst(
        .opcode(opcode),
        .func3(func3),
        .MemRead(MemRead),
        .MemtoReg(MemtoReg),
        .ALUop(ALUop),
        .MemWrite(MemWrite),
        .ALUSrc(ALUSrc),
        .RegWrite(RegWrite),
        .lui(lui),
        .U_type(U_type),
        .jal(jal),
        .jalr(jalr),
        .beq(beq),
        .bne(bne),
        .blt(blt),
        .bge(bge),
        .bltu(bltu),
        .bgeu(bgeu),
        .RW_type(RW_type)
    );
       
        alu_control alu_control_inst(
        .ALUop(ALUop),
        .func3(func3),
        .func7(func7),
        .ALUctl(ALUctl)
    );
       
endmodule

使用特权

评论回复
51
9dome猫|  楼主 | 2022-6-28 15:24 | 只看该作者
五.CPU的实现
1. RISC-V核心
将数据通路和及控制信号连接。

使用特权

评论回复
52
9dome猫|  楼主 | 2022-6-28 15:26 | 只看该作者
模块的输入输出端口定义如下:

使用特权

评论回复
53
9dome猫|  楼主 | 2022-6-28 15:27 | 只看该作者
代码如下:
module riscv(
        input clk,
        input rst_n,
        input [31:0]instr,
        input [31:0]Rd_mem_data,
       
        output [7:0]rom_addr,
       
        output [31:0]Wr_mem_data,
        output W_en,
        output R_en,
        output [31:0]ram_addr,
        output [2:0]RW_type
    );
       
        wire [6:0]opcode;
        wire [2:0]func3;
        wire func7;
        wire MemtoReg;
        wire ALUSrc;
        wire RegWrite;
        wire lui;
        wire U_type;
        wire jal;
        wire jalr;
        wire beq;
        wire bne;
        wire blt;
        wire bge;
        wire bltu;
        wire bgeu;
        wire [3:0]ALUctl;
       
       
       
        control control_inst (
    .opcode(opcode),
    .func3(func3),
    .func7(func7),
    .MemRead(R_en),
    .MemtoReg(MemtoReg),
    .MemWrite(W_en),
    .ALUSrc(ALUSrc),
    .RegWrite(RegWrite),
        .lui(lui),
        .U_type(U_type),
    .jal(jal),
    .jalr(jalr),
    .beq(beq),
    .bne(bne),
    .blt(blt),
    .bge(bge),
    .bltu(bltu),
    .bgeu(bgeu),
    .RW_type(RW_type),
    .ALUctl(ALUctl)
    );
       
        datapath datapath_inst (
    .clk(clk),
    .rst_n(rst_n),
    .instr(instr),
    .MemtoReg(MemtoReg),
    .ALUSrc(ALUSrc),
    .RegWrite(RegWrite),
        .lui(lui),
        .U_type(U_type),
    .jal(jal),
    .jalr(jalr),
    .beq(beq),
    .bne(bne),
    .blt(blt),
    .bge(bge),
    .bltu(bltu),
    .bgeu(bgeu),
    .ALUctl(ALUctl),
    .Rd_mem_data(Rd_mem_data),
    .rom_addr(rom_addr),
    .Wr_mem_data(Wr_mem_data),
        .ALU_result(ram_addr),
        .opcode(opcode),
        .func3(func3),
        .func7(func7)
    );

endmodule

使用特权

评论回复
54
9dome猫|  楼主 | 2022-6-28 15:28 | 只看该作者
2.完整CPU
接入指令存储器和数据存储器。
代码如下:
module riscv_top(
        input clk,
        input rst_n,
        output [7:0]rom_addr
    );

//        wire [7:0]rom_addr;
        wire [31:0]ram_addr;
        wire [31:0]instr;
        wire [31:0]Rd_mem_data;
        wire [31:0]Wr_mem_data;
        wire W_en;
        wire R_en;
        wire [2:0]RW_type;
       
        instr_memory instr_memory_inst (
    .addr(rom_addr),
    .instr(instr)
    );

        riscv riscv_inst (
    .clk(clk),
    .rst_n(rst_n),
    .instr(instr),
    .Rd_mem_data(Rd_mem_data),
    .rom_addr(rom_addr),
    .Wr_mem_data(Wr_mem_data),
    .W_en(W_en),
    .R_en(R_en),
    .ram_addr(ram_addr),
    .RW_type(RW_type)
    );

       
       
       
        data_memory data_memory_inst (
    .clk(clk),
    .rst_n(rst_n),
    .W_en(W_en),
    .R_en(R_en),
    .addr(ram_addr),
    .RW_type(RW_type),
    .din(Wr_mem_data),
    .dout(Rd_mem_data)
    );       

endmodule

使用特权

评论回复
55
9dome猫|  楼主 | 2022-6-28 15:29 | 只看该作者
3.整体预览
最终的代码结构如下:

使用特权

评论回复
56
9dome猫|  楼主 | 2022-6-28 15:29 | 只看该作者
FPGA工具生成的RTL图如下:

使用特权

评论回复
57
吾要单片机| | 2022-6-28 15:38 | 只看该作者
很好!支持楼主!

使用特权

评论回复
58
janewood| | 2022-8-16 19:53 | 只看该作者
单周期处理器有什么特点呢

使用特权

评论回复
59
robincotton| | 2022-8-17 15:52 | 只看该作者
这个单片机需要学习Verilog吗

使用特权

评论回复
60
cashrwood| | 2022-8-20 16:00 | 只看该作者
RISC-V处理器好用吗   

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则