RISC CPU处理器五级流水线 IF ID EX MEM WB 的编写@计算机组成原理

大二做的一个计算机组成原理课程设计,用verilog实现一个五级流水线的CPU。
主要实现了加减、比较、左移右移、条件跳转等的精简指令集。

`timescale 1ns / 1ps

`define idle 1'b0
`define exec 1'b1
//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'b01010
`define SUBI 5'b01011
`define SUBC 5'b10010
`define CMP 5'b01100
//Logical/Shift
`define AND 5'b01101
`define OR 5'b01110
`define XOR 5'b01111
`define SLL 5'b00100
`define SRL 5'b00110
`define SLA 5'b00101
`define SRA 5'b00111
//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
//************************************************//
//* You need to complete the design below        *//
//* by yourself according to your operation set  *//
//************************************************//
module CPU(
input [15:0]i_datain,
input [15:0]d_datain,
input clock,
input reset,
input enable,
input start,
//input [3:0]select_y,
//output reg [15:0]y,
output [7:0]i_addr,
output [7:0]d_addr,
output [15:0]d_dataout,
output d_we
);

reg [15:0]gr[7:0];

reg state;
reg next_state;

reg [7:0]pc;

reg [15:0]id_ir;
reg [15:0]ex_ir;
reg [15:0]mem_ir;
reg [15:0]wb_ir;

reg [15:0]reg_A;
reg [15:0]reg_B;
reg [15:0]reg_C;
reg [15:0]reg_C1;

reg [15:0]smdr;
reg [15:0]smdr1;

wire [15:0]ALUo;

reg nf,zf,dw;
wire cf;    

assign i_addr = pc;
assign d_addr = reg_C[7:0];
assign d_we = dw;
assign d_dataout = smdr1;

//************* CPU control *************//
always @(posedge clock)
    begin
        if (!reset)
            state <= `idle;
        else
            state <= next_state;
    end

always @(*)
    begin
        case (state)
            `idle : 
                if ((enable == 1'b1) 
                && (start == 1'b1))
                    next_state <= `exec;
                else    
                    next_state <= `idle;
            `exec :
                if ((enable == 1'b0) 
                || (wb_ir[15:11] == `HALT))
                    next_state <= `idle;
                else
                    next_state <= `exec;
        endcase
    end

//************* IF *************//
always @(posedge clock or negedge reset)
    begin
        if (!reset)
            begin
                id_ir <= 0;
                pc <= 0;
            end

        else if (state ==`exec)
            begin
                id_ir <= i_datain;

                if((mem_ir[15:11] == `JUMP)
                || (mem_ir[15:11] == `JMPR)
                ||  ((mem_ir[15:11] == `BZ)
                    && (zf == 1'b1)) 
                || ((mem_ir[15:11] == `BNZ)
                    && (zf == 1'b0)) 
                || ((mem_ir[15:11] == `BN)
                    && (nf == 1'b1))
                || ((mem_ir[15:11] == `BNN)
                    && (nf == 1'b0))
                || ((mem_ir[15:11] == `BC)
                    && (cf == 1'b1))
                || ((mem_ir[15:11] == `BNC)
                    && (cf == 1'b0)))
                    pc <= reg_C[7:0];//if jumped
                else
                    pc <= pc + 1;//if not jumped
            end
    end

//************* ID *************//
always @(posedge clock or negedge reset)
    begin
        if (!reset)
            begin
                ex_ir<=0;
                reg_A<=0;
                reg_B<=0;
                smdr<=0;
            end

        else if (state == `exec)
            begin
                ex_ir <= id_ir;

                if ((id_ir[15:11] == `LDIH)
                || (id_ir[15:11] == `ADDI) || (id_ir[15:11] == `SUBI)
                || (id_ir[15:11] == `JMPR)
                || (id_ir[15:11] == `BZ) || (id_ir[15:11] == `BNZ)
                || (id_ir[15:11] == `BN) || (id_ir[15:11] == `BNN)
                || (id_ir[15:11] == `BC) || (id_ir[15:11] == `BNC))
                    reg_A <= gr[(id_ir[10:8])];//r1

                else if(id_ir[15:11] == `JUMP)
                    reg_A <= gr[(id_ir[7:0])];//val2+val3

                else
                    reg_A <= gr[id_ir[6:4]];//r2
                ///////////////////////////////////////////////////////////

                if ((id_ir[15:11] == `LOAD) || (id_ir[15:11] == `STORE) 
                || (id_ir[15:11] == `SLL) || (id_ir[15:11] == `SRL) 
                || (id_ir[15:11] == `SLA) || (id_ir[15:11] == `SRA))
                    reg_B <= {12'b0000_0000_0000, id_ir[3:0]};//val3

                else if (id_ir[15:11] == `STORE)
                    begin
                        reg_B <= {12'b0000_0000_0000, id_ir[3:0]};//val3
                        smdr <= gr[id_ir[10:8]];
                    end

                else if ((id_ir[15:11] == `ADDI) || (id_ir[15:11] == `SUBI) 
                || (id_ir[15:11] == `BZ) || (id_ir[15:11] == `BNZ) 
                || (id_ir[15:11] == `BN) || (id_ir[15:11] == `BNN) 
                || (id_ir[15:11] == `BC) || (id_ir[15:11] == `BNC) 
                || (id_ir[15:11] == `JMPR))
                    reg_B <= {8'b0000_0000,id_ir[7:0]};//{val2,val3}

                else if (id_ir[15:11] == `JUMP) 
                    reg_B <= 0;//0

                else if ((id_ir[15:11] == `ADDC) || (id_ir[15:11] == `SUBC))
                    reg_B <= gr[id_ir[2:0]]+cf;//r3+cf

                else if (id_ir[15:11] == `LDIH)
                   reg_B <= {id_ir[7:0],8'b0000_0000};//{val2,val3,8'b0000_0000}

                else
                   reg_B <= gr[id_ir[2:0]];
            end
    end

ALU alu(
    .a(reg_A),
    .b(reg_B),
    .ir(ex_ir[15:11]),
    .ALUo(ALUo),
    .cf(cf)
);

//************* EX *************//  
always @(posedge clock or negedge reset)
    begin
        if (!reset)
            begin
                reg_C<=0;
                mem_ir<=0;
                zf<=0;
                nf<=0;
                dw<=0;
                smdr1<=0;
            end

        else if (state == `exec)
            begin
                mem_ir <= ex_ir;
                reg_C <= ALUo;

                if ((ex_ir[15:11] == `ADD) || (ex_ir[15:11] == `ADDI) || (ex_ir[15:11] == `ADDC)
                || (ex_ir[15:11] == `SUB) || (ex_ir[15:11] == `SUBI) || (ex_ir[15:11] == `SUBC)
                || (ex_ir[15:11] == `CMP))
                    begin
                        if (ALUo == 16'b0000_0000_0000_0000)
                            zf <= 1'b1;
                        else
                            zf <= 1'b0;
                        begin
                        if (ALUo[15] == 1'b1)
                            nf <= 1'b1;
                        else
                            nf <= 1'b0;
                        end
                    end
                if (ex_ir[15:11] == `STORE)
                    begin
                        dw <= 1'b1;
                        smdr1 <= smdr;
                    end
                else
                    dw <= 1'b0;
            end
    end

//************* MEM *************//
always @(posedge clock or negedge reset)
    begin
        if (!reset)
            begin
                reg_C1<=0;
                wb_ir<=0;
            end

        else if (state == `exec)
            begin
                wb_ir <= mem_ir;

                if (mem_ir[15:11] == `LOAD)
                    reg_C1 <= d_datain;
                else
                    reg_C1 <= reg_C;
            end
    end     

//************* WB *************//
always @(posedge clock or negedge reset)
    begin
        if (!reset)
            begin
                gr[0] <= 16'b0000_0000_0000_0000;
                gr[1] <= 16'b0000_0000_0000_0000;
                gr[2] <= 16'b0000_0000_0000_0000;
                gr[3] <= 16'b0000_0000_0000_0000;
                gr[4] <= 16'b0000_0000_0000_0000;
                gr[5] <= 16'b0000_0000_0000_0000;
                gr[6] <= 16'b0000_0000_0000_0000;
                gr[7] <= 16'b0000_0000_0000_0000;
            end

        else if (state == `exec)
            begin
                if ((wb_ir[15:11] == `LOAD) || (wb_ir[15:11] == `LDIH)
                || (wb_ir[15:11] == `ADD)|| (wb_ir[15:11] == `ADDI) || (wb_ir[15:11] == `ADDC)
                || (wb_ir[15:11] == `SUB)|| (wb_ir[15:11] == `SUBI) || (wb_ir[15:11] == `SUBC)
                || (wb_ir[15:11] == `AND)|| (wb_ir[15:11] == `OR) || (wb_ir[15:11] == `XOR)
                || (wb_ir[15:11] == `SLL)|| (wb_ir[15:11] == `SRL) 
                || (wb_ir[15:11] == `SLA)|| (wb_ir[15:11] == `SRA))
                    gr[wb_ir[10:8]] <= reg_C1;
            end
    end

endmodule

module ALU(
input [15:0]a,
input [15:0]b,
input [4:0]ir,
output reg [15:0]ALUo,
output reg cf
);
reg eat;
always@(a or b or ir)begin
    if(ir==`LOAD || ir==`STORE
    || ir==`ADD || ir==`ADDI || ir==`ADDC
    || ir==`JUMP || ir==`JMPR 
    || ir==`BZ || ir==`BNZ || ir==`BN || ir==`BNN || ir==`BC || ir==`BNC)
        {cf,ALUo} <= a+b;
    else if(ir==`SUB || ir==`SUBI || ir==`SUBC
    || ir==`CMP)
        ALUo <= $signed(a)-b;
    else if(ir==`AND)
        ALUo <= a&b;
    else if(ir==`OR)
        ALUo <= a|b;
    else if(ir==`XOR)
        ALUo <= a^b;
    else if(ir==`SLL)
        ALUo <= a<
    else if(ir==`SRL)
        ALUo <= a>>b;
    else if(ir==`SLA)
        ALUo <= $signed(a)<<
    else if(ir==`SRA)
        ALUo <= $signed(a)>>>b;
    else
        ALUo <= 16'bXXXXXXXXXXXXXXXX;
end
endmodule

你可能感兴趣的:(其他)