leg.v

来自「verilog hdl编写,六段流水线CPU.程序完整」· Verilog 代码 · 共 1,311 行 · 第 1/5 页

V
1,311
字号

//if it is a load and the base addr is updated, then just leave it as the last instruction.
assign          f_lsm_load_base_addr = (f_lsm_inst_backup[20] && f_lsm_counter[3:0] == f_lsm_inst_backup[19:16] && f_lsm_rout) ? 1'b1 : 1'b0;
assign          f_lsm_generated_inst_valid = (((f_lsm_state == 1 || f_lsm_state == 2) && f_lsm_rout && !f_lsm_load_base_addr) || (f_lsm_state == 3 && f_lsm_load_base_addr_r));
assign          f_op_decoded_ldm        = (i_datain[27:25] == 3'b100 && i_datain[20] == 1'b1 && !pc_reload && !pc_reload_r) ? 1'b1 : 1'b0;
assign          f_op_decoded_stm        = (i_datain[27:25] == 3'b100 && i_datain[20] == 1'b0 && !pc_reload && !pc_reload_r) ? 1'b1 : 1'b0;

//load store state machine;
always@(posedge clk or posedge rst)
begin
        if (rst) begin
                f_lsm_state <= 2'h0;
                f_lsm_counter <= 4'hf;
                f_lsm_rlist <= 16'h0;
                f_lsm_addr_counter <= 4'h0;
                f_lsm_inst_backup <= 31'h0;
        end
        else begin
                if (f_en) begin
                        case(f_lsm_state)
                        0: begin
                                if (f_op_decoded_ldm && !pc_reload && !pc_reload_r) begin
                                        f_lsm_state <= 1;
                                        f_lsm_counter <= 4'h0;
                                        f_lsm_inst_backup <= i_datain[31:0];
                                        if (i_datain[24])       //increase after
                                                f_lsm_addr_counter <= 4'h1;
                                        else                    //increase before
                                                f_lsm_addr_counter <= 4'h0;
                                        f_lsm_rlist <= i_datain[15:0];
                                end
                                else if (f_op_decoded_stm && !pc_reload && !pc_reload_r) begin
                                        f_lsm_state <= 2;
                                        f_lsm_counter <= 4'hf;
                                        f_lsm_inst_backup <= i_datain[31:0];
                                        if (i_datain[24])       //increase after
                                                f_lsm_addr_counter <= 4'h1;
                                        else                    //increase before
                                                f_lsm_addr_counter <= 4'h0;
                                        f_lsm_rlist <= i_datain[15:0];
                                end
                        end
                        1: begin        //ldm
                                //if the instruction before the lsm is jump and has been exec, then, the lsm should be
                                //invalid
                                if (pc_reload || pc_reload_r) begin
                                        f_lsm_state <= 0;
                                        f_lsm_counter <= 4'h0;
                                end
                                if (f_lsm_counter == 4'hf ) begin        //return to idle
                                        f_lsm_state <= 3;
                                        //f_lsm_counter <= 4'h0;
                                end
                                else begin
                                        f_lsm_counter <= f_lsm_counter + 4'h1;
                                        f_lsm_rlist[14:0] <= f_lsm_rlist[15:1];
                                        f_lsm_rlist[15] <= 1'b0;
                                        //increase address
                                        if (f_lsm_rlist[0]) begin
                                                f_lsm_addr_counter <= f_lsm_addr_counter + 1;
                                        end
                                end
                        end
                        2: begin        //stm
                                //if the instruction before the lsm is jump and has been exec, then, the lsm should be
                                //invalid
                                if (pc_reload || pc_reload_r) begin
                                        f_lsm_state <= 0;
                                        f_lsm_counter <= 4'hf;
                                end
                                if (f_lsm_counter == 4'h0 ) begin        //return to idle
                                        f_lsm_state <= 3;
                                        //f_lsm_counter <= 4'h0;
                                end
                                else begin
                                        f_lsm_counter <= f_lsm_counter - 4'h1;
                                        f_lsm_rlist[15:1] <= f_lsm_rlist[14:0];
                                        f_lsm_rlist[0] <= 1'b0;
                                        //increase address
                                        if (f_lsm_rlist[15]) begin
                                                f_lsm_addr_counter <= f_lsm_addr_counter + 1;
                                        end
                                end
                        end
                        //last load for the
                        3: begin
                                f_lsm_state <= 0;
                                f_lsm_counter <= 4'h0;
                                //f_lsm_addr_counter <= 4'h0;
                        end
                        endcase
                end
        end
end

always@(posedge clk or posedge rst)
begin
        if (rst) begin
                f_lsm_state_d <=  2'h0;
        end
        else begin
                if (f_en)
                        f_lsm_state_d <=  f_lsm_state;
        end
end

//------------------------------------------------------------------------------end of fetch stage


//------------------------------------------------------------------------------decode stage
assign          d_en = ~d_wait;
assign          d_valid = d_valid_r & (~a_br_exec) & (~w_load_r15);
wire            d_foward_ena;
//register op
always@(posedge clk or posedge rst)
begin
        if (rst) begin
                d_inst <= 32'he1a10001;        //mov r1,r1
        end
        else begin
                if (d_en)
                        d_inst <= f_inst;
        end
end

always@(posedge clk or posedge rst)
begin
        if (rst) begin
                d_valid_r <=  1'b0;
        end
        else begin
                if (d_en)
                        d_valid_r <= f_valid;
        end
end

always@(posedge clk or posedge rst)
begin
        if (rst) begin
                d_op_decoded_raddrc <=  5'b0;
        end
        else begin
                if (d_en) begin
                        d_op_decoded_raddrc <=  f_op_decoded_raddrc;
                end
        end
end

always@(posedge clk or posedge rst)
begin
        if (rst) begin
                d_lsm_restore_rd_valid <= 1'b0;
        end
        else begin
                if (d_en)
                        d_lsm_restore_rd_valid <= f_lsm_restore_rd_valid;
        end
end

always@(posedge clk or posedge rst)
begin
        if (rst) begin
                d_lsm_inst_count <= 4'h0;
        end
        else begin
                if (d_en) begin
                        if (f_lsm_state) begin
                                if (f_lsm_rout) begin
                                        d_lsm_inst_count <= d_lsm_inst_count + 4'h1;
                                end
                        end
                        else begin
                                d_lsm_inst_count <= 4'h0;
                        end  
                end
        end
end



always@(posedge clk or posedge rst)
begin
        if (rst) begin
                r_lsm_inst_count <= 4'h0;
        end
        else begin
                if (r_en)
                        r_lsm_inst_count <= d_lsm_inst_count;
        end
end

always@(posedge clk or posedge rst)
begin
        if (rst) begin
                a_lsm_inst_count <= 4'h0;
        end
        else begin
                if (a_en)
                        a_lsm_inst_count <= r_lsm_inst_count;
        end
end

always@(posedge clk or posedge rst)
begin
        if (rst) begin
                a_lsm_inst_store_addr <= 32'h0;
        end
        else begin
                if (a_en) begin
                        if (r_op_decoded_ls_u)
                                a_lsm_inst_store_addr[31:2] <= rf_rdatac[31:2] - a_lsm_inst_count ;
                        else
                                a_lsm_inst_store_addr[31:2] <= rf_rdatac[31:2] + a_lsm_inst_count ;
                        a_lsm_inst_store_addr[1:0] <= rf_rdatac[1:0];
                end
        end
end

//instruction decoding
assign          d_op_condcode                           =       d_inst[31:28];                                  //4 bit
//type: data processing decoding
assign          d_op_opcode                             =       d_inst[24:21];                                  //4 bit
assign          d_op_s_bit                              =       d_inst[20];                                     //1 bit

assign          d_op_shift_amount                       =       d_inst[11:07];                                  //5 bit
assign          d_op_shift                              =       d_inst[06:05];                                  //2 bit
assign          d_op_rm                                 =       d_inst[03:00];                                  //4 bit
assign          d_op_rs                                 =       d_inst[11:08];                                  //4 bit     
assign          d_op_rn                                 =       (d_op_deocded_mult_accm)? d_inst[15:12] : d_inst[19:16];                                  //4 bit
assign          d_op_rd                                 =       (d_op_decoded_mul || d_op_deocded_mult_accm) ? d_inst[19:16] : d_inst[15:12];       //multiplier has a different rd                           //4 bit
assign          d_op_immediate_ls                       =       d_inst[11:00];                                  //12 bit 
assign          d_op_s_bit                              =       d_inst[20];
//condition code decoding
assign          d_op_cond_eqz           =       (d_op_condcode == 4'b0000) ? 1'b1 : 1'b0;       //EQ Equal Z set                                                                 
assign          d_op_cond_nez           =       (d_op_condcode == 4'b0001) ? 1'b1 : 1'b0;       //NE Not equal Z clear                                                           
assign          d_op_cond_csc           =       (d_op_condcode == 4'b0010) ? 1'b1 : 1'b0;       //CS Unsigned higher, or same C set                                              
assign          d_op_cond_ccc           =       (d_op_condcode == 4'b0011) ? 1'b1 : 1'b0;       //CC Unsigned lower C clear                                                      
assign          d_op_cond_min           =       (d_op_condcode == 4'b0100) ? 1'b1 : 1'b0;       //MI Negative N set                                                              
assign          d_op_cond_pln           =       (d_op_condcode == 4'b0101) ? 1'b1 : 1'b0;       //PL Positive, or zero N clear                                                   
assign          d_op_cond_vsv           =       (d_op_condcode == 4'b0110) ? 1'b1 : 1'b0;       //VS Overflow V set                                                              
assign          d_op_cond_vcv           =       (d_op_condcode == 4'b0111) ? 1'b1 : 1'b0;       //VC No overflow V clear                                                         
assign          d_op_cond_hic           =       (d_op_condcode == 4'b1000) ? 1'b1 : 1'b0;       //HI Unsigned higher C set, Z clear                                              
assign          d_op_cond_lsc           =       (d_op_condcode == 4'b1001) ? 1'b1 : 1'b0;       //LS Unsigned lower, or same C clear, Z set                                      
assign          d_op_cond_gen           =       (d_op_condcode == 4'b1010) ? 1'b1 : 1'b0;       //GE Greater, or equal N=V (N and V set or N and V clear)                        
assign          d_op_cond_ltn           =       (d_op_condcode == 4'b1011) ? 1'b1 : 1'b0;       //LT Less than N<>V (N set and V clear) or (N clear and V set)                   
assign          d_op_cond_gtz           =       (d_op_condcode == 4'b1100) ? 1'b1 : 1'b0;       //GT Greater than Z clear, N=V (N and V set or N and V clear)                    
assign          d_op_cond_lez           =       (d_op_condcode == 4'b1101) ? 1'b1 : 1'b0;       //LE Less than, or equal Z set or N<>V (N set and V clear) or (N clear and V set)
assign          d_op_cond_al            =       (d_op_condcode == 4'b1110) ? 1'b1 : 1'b0;       //AL Always Flag ignored     always run                                                    
assign          d_op_cond_nv            =       (d_op_condcode == 4'b1111) ? 1'b1 : 1'b0;       //NV-NEVER never run


//operation decoding
assign          d_op_decoded_and        =       (d_op_opcode == 4'b0000) ? 1'b1 : 1'b0;         //logic and                    |rd = rn & shifter_operand
assign          d_op_decoded_eor        =       (d_op_opcode == 4'b0001) ? 1'b1 : 1'b0;         //logical exclusive or         |rd = rn ^ shifter_operand (exclusive)
assign          d_op_decoded_sub        =       (d_op_opcode == 4'b0010) ? 1'b1 : 1'b0;         //substract                    |rd = rn - shifter_operand
assign          d_op_decoded_rsb        =       (d_op_opcode == 4'b0011) ? 1'b1 : 1'b0;         //reverse substract            |rd = shifter_operand - rn
assign          d_op_decoded_add        =       (d_op_opcode == 4'b0100) ? 1'b1 : 1'b0;         //add                          |rd = rn + shifter_operand
assign          d_op_decoded_adc        =       (d_op_opcode == 4'b0101) ? 1'b1 : 1'b0;         //add with carry               |rd = rn + shifter_operand + carry_flag
assign          d_op_decoded_sbc        =       (d_op_opcode == 4'b0110) ? 1'b1 : 1'b0;         //substract with carry         |rd = rn - shifter_operand - (not)carry_flag
assign          d_op_decoded_rsc        =       (d_op_opcode == 4'b0111) ? 1'b1 : 1'b0;         //reverse substract with carry |rd = shifter_operand - rn - (not)carry_flag
assign          d_op_decoded_tst        =       (d_op_opcode == 4'b1000) ? 1'b1 : 1'b0;         //test                         |upgrade flags after rn & shifter_oprand
assign          d_op_decoded_teq        =       (d_op_opcode == 4'b1001) ? 1'b1 : 1'b0;         //test equivalence             |upgrade flags after rn | shifter_oprand
assign          d_op_decoded_cmp        =       (d_op_opcode == 4'b1010) ? 1'b1 : 1'b0;         //compare                      |upgrade flags after rn - shifter_oprand

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?