leg.v

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

V
1,311
字号
assign          d_op_decoded_cmn        =       (d_op_opcode == 4'b1011) ? 1'b1 : 1'b0;         //compare negated              |upgrade flags after rn + shifter_oprand
assign          d_op_decoded_orr        =       (d_op_opcode == 4'b1100) ? 1'b1 : 1'b0;         //logical inclusive or         |rd = rn | shifter_operand
assign          d_op_decoded_mov        =       (d_op_opcode == 4'b1101) ? 1'b1 : 1'b0;         //move                         |rd = shifter_operand
assign          d_op_decoded_bic        =       (d_op_opcode == 4'b1110) ? 1'b1 : 1'b0;         //bit clear                    |rd = rn and not(shifter_operand)
assign          d_op_decoded_mvn        =       (d_op_opcode == 4'b1111) ? 1'b1 : 1'b0;         //move not                     |rd = not(shifter_operand)
assign          d_op_decoded_mul        =       (d_inst[27:21] == 7'b0000000 && d_inst[7:4] == 4'b1001) ? 1'b1 : 1'b0;   //SHORT MULTIPLY

//dsp inst
assign          d_op_deocded_mult_long  =       (d_inst[27:21] == 7'b0000110 && d_inst[7:4] == 4'b1001) ? 1'b1 : 1'b0;   //long MULTIPLY
assign          d_op_deocded_mult_accm  =       (d_inst[27:21] == 7'b0000001 && d_inst[7:4] == 4'b1001) ? 1'b1 : 1'b0;   //multiply and accumulaton

//load /store decoding
assign          d_op_decoded_ar = (d_inst[27:26] == 2'b00) ? 1'b1 : 1'b0; 
assign          d_op_decoded_ldr        =       (d_inst[27:26] == 2'b01 && d_inst[20] == 1) ? 1'b1 : 1'b0;
assign          d_op_decoded_str        =       (d_inst[27:26] == 2'b01 && d_inst[20] == 0) ? 1'b1 : 1'b0;
assign          d_op_decoded_ls_b_or_w  =       ((d_op_decoded_ldr || d_op_decoded_str) && d_inst[22]) ? 1'b1 : 1'b0; //1 means byte and 0 means word or not a load or store
assign          d_op_decoded_ls_u       =       ((d_op_decoded_ldr || d_op_decoded_str) && !d_inst[23]) ? 1'b1 : 1'b0; //1 means subtract and 0 means add or not a load or store
assign          d_op_decoded_ls_p       =       ((d_op_decoded_ldr || d_op_decoded_str) && ((!d_inst[24] && !d_inst[21]) || (d_inst[24] && d_inst[21]))) ? 1'b1 : 1'b0; //1 means update rn and 0 means do not update or not a load or store
assign          d_op_decoded_ls_pre_addr=       ((d_op_decoded_ldr || d_op_decoded_str) && !d_inst[24] && !d_inst[21]) ? 1'b1 : 1'b0;
//branch and link
assign          d_op_decoded_br         =       (d_inst[27:25] == 3'b101 || d_op_decoded_swi) ? 1'b1 : 1'b0;
assign          d_op_decoded_addr_ext   =       (d_inst[23]) ? {8'b11111111, d_inst[23:0]} : {8'b00000000, d_inst[23:0]};
assign          d_op_decoded_br_l_bit   =       d_inst[24];

//software interrupt
assign          d_op_decoded_swi        =       (d_inst[27:24] == 4'b1111)? 1'b1 : 1'b0;
assign          d_op_decoded_undefined  =       (d_inst[27:23] == 5'b00110 && d_inst[21:20] == 2'b00 ||
                                                 d_inst[27:25] == 3'b011 && d_inst[4] == 1'b1 ||
                                                 d_inst[31:27] == 5'b11110 ||
                                                 d_inst[31:25] == 7'b1111100 ||
                                                 d_inst[31:24] == 8'b11111111)? 1'b1 : 1'b0;
                                                 
assign          d_op_decoded_msr        =       (d_inst[27:26] == 2'b00 && d_inst[24:23] == 2'b10 && d_inst[21:20] == 2'b10)? 1'b1 : 1'b0;
assign          d_op_decoded_mrs        =       (d_inst[27:23] == 5'b00010 && d_inst[21:20] == 2'b00) ? 1'b1 : 1'b0;
assign          d_op_deocded_msr_mask_c =       (d_inst[19])? 8'hff : 8'h00;
assign          d_op_deocded_msr_mask_x =       (d_inst[18])? 8'hff : 8'h00;
assign          d_op_deocded_msr_mask_s =       (d_inst[17])? 8'hff : 8'h00;
assign          d_op_deocded_msr_mask_f =       (d_inst[16])? 8'hff : 8'h00;
assign          d_op_deocded_msr_mask   =       {d_op_deocded_msr_mask_c, d_op_deocded_msr_mask_x, d_op_deocded_msr_mask_s, d_op_deocded_msr_mask_f};

assign          d_op_decoded_msr_r_bit  =       d_inst[22];
assign          d_op_decoded_mrs_r_bit  =       d_inst[22];

//foward enable
assign          d_foward_ena            =       (d_op_rd == f_op_rn && d_valid && f_inst[27:26] != 2'b10)? 1'b1 : 1'b0;
assign          d_ar_load_r15           =       (!d_op_decoded_br && d_op_decoded_ar && d_op_rd == 15 && d_write_porta_ena)? 1'b1 : 1'b0;

//rf write enable for arithmetic, load, store
//port a is used for arithmetic and short mul and link addr and load store post addr
assign          d_write_porta_ena       =       ((d_valid &&((d_inst[27:26] == 2'b00 && d_op_decoded_cmp == 0 && d_op_decoded_cmn == 0 && d_op_decoded_tst == 0 && d_op_decoded_teq == 0 && d_op_deocded_mult_accm == 0) ||        //arithmetic
                                                 //(d_inst[27:26] == 2'b01 && d_inst[4] == 0 && d_op_decoded_ls_p) || 
                                                 (d_inst[27:26] == 2'b01 && d_op_decoded_ls_p) ||       //what does the d_inst[4] means?                                                                   //load store post addr
                                                 (d_op_decoded_br && d_op_decoded_br_l_bit) ||  
                                                 (d_op_decoded_mrs) ||                          //move cpsr also need a write                                                                                     //branch link addr             
                                                 d_op_decoded_swi)) ||
                                                 d_lsm_restore_rd_valid )? 1'b1 : 1'b0;                                                                                                      //software interrupt return addr
assign          d_write_portb_ena       =       (d_valid && (d_inst[27:26] == 2'b01 && d_inst[20]) ||  //load
                                                //(d_valid && (d_inst[27:26] == 2'b01 && d_inst[20] && d_inst[4] == 0) ||  //seems misunderstanding the load inst
                                                d_op_deocded_mult_long || d_op_deocded_mult_accm) ? 1'b1 : 1'b0;     //long mult and multiply and accumulation
//----------------------------------shifter operation
assign          d_shift_by_register     =       (!d_inst[7] && d_inst[4]) ? 1'b1 :1'b0;         //not full decoded
//barrier shifter
assign          shifter_opcode          =       (!d_inst[25] && (d_op_decoded_ldr || d_op_decoded_str || d_op_deocded_mult_accm)) ? 5'b0 : (d_inst[25]) ? {d_inst[11:8], 1'b0}  : (d_shift_by_register) ? rf_rdatab[4:0] : d_inst[11:7];    //
assign          shifter_oprand          =       (!d_inst[25] && (d_op_decoded_ldr || d_op_decoded_str)) ? {20'h0,d_op_immediate_ls} : (d_inst[25]) ? {24'h0, d_inst[07:0]} : (rf_raddra_r == 15)? {2'b0, pc, 2'b0} : rf_rdataa;
//why I make such mistake??
//assign          shifter_opcode          =       (!d_inst[25] && (d_op_decoded_ldr || d_op_decoded_str || d_op_deocded_mult_accm)) ? 5'b0 : (d_inst[25]) ? {d_inst[11:8], 1'b0}  : (d_shift_by_register) ? rf_rdataa[4:0] : d_inst[11:7];    //
//assign          shifter_oprand          =       (!d_inst[25] && (d_op_decoded_ldr || d_op_decoded_str)) ? {20'h0,d_op_immediate_ls} : (d_inst[25]) ? {24'h0, d_inst[07:0]} : (rf_raddra_r == 15)? {2'b0, pc, 2'b0} : rf_rdatab;
assign          shifter_direction       =       (d_shifter_op_rotater_immd) ? 1'b0 : (d_inst[6:5] == 2'b00) ? 1'b1 : 1'b0;       
//if the next inst will update the c flag by shifter result, carry in can use a foward result, otherwise it need a stall
assign          shifter_carry_in        =       (!r_op_decoded_carry_from_arithm && r_op_s_bit) ? shifter_carry_r : cpsr_c_o;                                       //or the alu output?



assign          d_shifter_op_logic_shiftl_by_immd = (d_inst[6:4] == 3'b000) ? 1'b1 : 1'b0;
assign          d_shifter_op_logic_shiftr_by_immd = (d_inst[6:4] == 3'b010) ? 1'b1 : 1'b0;
assign          d_shifter_op_arthm_shiftr_by_immd = (d_inst[6:4] == 3'b100) ? 1'b1 : 1'b0;
assign          d_shifter_op_rotater_by_immd      = (d_inst[6:4] == 3'b110 && d_inst[11:7] != 5'b00000) ? 1'b1 : 1'b0;
assign          d_shifter_op_rotater_immd         = (d_inst[27:25] == 3'b001);

assign          d_shifter_op_logic_shiftl_by_regd = (!d_inst[25] && d_inst[7:4] == 4'b0001) ? 1'b1 : 1'b0;
assign          d_shifter_op_logic_shiftr_by_regd = (!d_inst[25] && d_inst[7:4] == 4'b0011) ? 1'b1 : 1'b0;
assign          d_shifter_op_arthm_shiftr_by_regd = (!d_inst[25] && d_inst[7:4] == 4'b0101) ? 1'b1 : 1'b0;
assign          d_shifter_op_rotater_by_regd      = (!d_inst[25] && d_inst[7:4] == 4'b0111) ? 1'b1 : 1'b0;
//for load and arithmetic, the decoding is different
assign          d_shifter_op_rotater_with_ext     = (((d_inst[25] == 0 && d_op_decoded_ar) || (d_inst[25] == 1 && (d_op_decoded_ldr || d_op_decoded_str))) && d_inst[11:4] == 8'b00000110) ? 1'b1 : 1'b0;

assign          shifter_mode            =     ((d_shifter_op_logic_shiftl_by_immd) ||
                                              ( d_shifter_op_logic_shiftl_by_regd))  ? 3'b000 :
                                              ((d_shifter_op_logic_shiftr_by_immd) ||  
                                              ( d_shifter_op_logic_shiftr_by_regd))  ? 3'b001 : 
                                              ((d_shifter_op_arthm_shiftr_by_immd) || 
                                              ( d_shifter_op_arthm_shiftr_by_regd))  ? 3'b010 :
                                              ((d_shifter_op_rotater_by_immd) || 
                                              ( d_shifter_op_rotater_by_regd) ||
                                              (d_shifter_op_rotater_immd))       ? 3'b011 : 
                                              (d_shifter_op_rotater_with_ext) ? 3'b100 : 3'b000;
                                              
                                              
leg_shifter     shifter_0(
        .din(shifter_oprand),
        .dout(shifter_result),
        .shift_oprand(shifter_opcode),
        .direction(shifter_direction),
        .mode(shifter_mode),
        .carry_in(shifter_carry_in),
        .carry_out(shifter_carry_out)
        );
        
always@(posedge clk or posedge rst)
begin
        if (rst) begin
                shifter_carry_r <=  1'b0;
                rf_raddra_r <= 5'h0;
        end
        else begin
                if (d_en) begin
                        shifter_carry_r <= shifter_carry_out;
                        rf_raddra_r <= rf_raddra;
                end
        end
end



//read the opranda

//control part
// there are some kinds of stall 
// current read address rn  == last write rd ----------------- cause 0 cycle stall by foward path
//done
// current read address rn  == last load post write rn ------- cause 0 cycle stall by foward path
//done
// current read address rn  == last store post write rn ------ cause 0 cycle stall by foward path
//done
// current read address rs or rm == last multipler result rl-- cause 1 cycle stall 
//done
// current read address rs or rm == last multipler result rh-- cause 2 cycle stall
//done
// current read address rn  == last multipler result rh------- cause 1 cycle stall
//done
// current read address rn  == last multipler result rl------- cause 0 cycle stall
//done
// current read_address rs or rm == last accm result rd------- cause 2 cycle stall
//done
// current read_address rn  == last accm result rd------------ cause 1 cycle stall
//done
// current shift with carry and last s bit ==1---------------- cause 1 cycle stall
//done
// load cpsr-------------------------------------------------- cause 4 cycle stall
// load/store multiple---------------------------------------- cause 18 cycle stall

assign          d_op_decoded_carry_from_arithm = (d_op_decoded_adc || d_op_decoded_add || d_op_decoded_cmn || d_op_decoded_cmp || d_op_decoded_rsb || d_op_decoded_rsc || d_op_decoded_sub || d_op_decoded_sbc) ? 1'b1 : 1'b0 ;
assign          d_ar_stall_d_shift_and_c_wait = (d_valid && d_op_s_bit && d_op_decoded_carry_from_arithm && d_op_s_bit && f_op_shift_rrx_pre);
wire            d_msr_stall;
//d_ls_stall_drd_eq_frs: current read address rs or rm == last load rd ------------- cause 2 cycle stall
//d_ls_stall_drn_eq_frs: current read address rs or rm == last ls post write rn ---- cause 1 cycle stall
//d_ls_stall_drd_eq_frn: current read address rn  == last load  rd ----------------- cause 1 cycle stall
//d_ar_stall_drd_eq_frs: current read address rs or rm == last write rd------------- cause 1 cycle stall
                                                                     //current is load and next is register                                                and  one of register equal
assign          d_ls_stall_drd_eq_frs   = (d_valid && (d_op_decoded_ldr) && (f_op_i_bit_pre && f_op_ls_pre || !f_op_i_bit_pre && f_op_ar_pre) && ((d_op_rd == f_op_rs_pre && f_op_rs_valid) || d_op_rd == f_op_rm_pre && f_op_rm_valid)) ? 1'b1 : 1'b0;
                                                                     //current is load or store           and need post writing  and next is register                                                and dfn = frs
assign          d_ls_stall_drn_eq_frs   = (d_valid && (d_op_decoded_ldr || d_op_decoded_str) && d_op_decoded_ls_p && (f_op_i_bit_pre && f_op_ls_pre || !f_op_i_bit_pre && f_op_ar_pre) && ((d_op_rn == f_op_rs_pre && f_op_rs_valid) || d_op_rn == f_op_rm_pre && f_op_rm_valid)) ? 1'b1 : 1'b0;
                                                                     //current is load  and 
assign          d_ls_stall_drd_eq_frn   = (d_valid && (d_op_decoded_ldr) && (d_op_rd == f_op_rn_pre)) ? 1'b1 : 1'b0;
                                               //current is arithmetic and  next is register                                         and 
assign          d_ar_stall_drd_eq_frs   = (d_valid && d_op_decoded_ar && (f_op_i_bit_pre && f_op_ls_pre || !f_op_i_bit_pre && f_op_ar_pre) && ((d_op_rd == f_op_rs_pre && f_op_rs_valid) || d_op_rd == f_op_rm_pre && f_op_rm_valid)) ? 1'b1 : 1'b0;
assign          d_msr_stall             = (d_valid && d_op_decoded_msr)? 1'b1 : 1'b0;
assign          d_stall                 = (f_lsm_state == 0 && (d_ls_stall_drd_eq_frs || d_ls_stall_drn_eq_frs || d_ls_stall_drd_eq_frn || d_ar_stall_drd_eq_frs || d_ar_stall_d_shift_and_c_wait || d_msr_stall)) ? 1'b1 : 1'b0;
//------------------------------------------------------------------------------end of decode stage


//------------------------------------------------------------------------------register stage
assign          r_en = ~d_wait;

wire            r_intr_exec;
assign          r_intr_exec = ((irq_ena && irq_in) || (fiq_ena && fiq_in))? 1'b1 : 1'b0;
assign          r_valid = (r_valid_r && a_br_exec == 1'b0 && w_load_r15 == 1'b0 && r_intr_exec == 1'b0)? 1'b1 : 1'b0;
//r_ls_stall_drd_eq_frs: current read address rs or rm == last load rd ------------- cause 1 cycle stall
                                                         //current is load and next is register  and  one of register equal
assign          r_ls_stall_drd_eq_frs = (r_valid && ((r_op_decoded_ldr) && (f_op_i_bit_pre && f_op_ls_pre || !f_op_i_bit_pre && f_op_ar_pre) &&(r_op_rd == f_op_rs_pre && f_op_rs_valid || r_op_rd == f_op_rm_pre && f_op_rm_valid))) ? 1'b1 : 1'b0;

//accum or mult long
assign          r_ar_accm_stall_drd_eq_frs = (r_valid && (r_op_deocded_mult_accm && (f_op_i_bit_pre && f_op_ls_pre || !f_op_i_bit_pre && f_op_ar_pre) && (r_op_rd == f_op_rs_pre && f_op_rs_valid || r_op_rd == f_op_rm_pre && f_op_rm_valid)));
assign          r_ar_mull_stall_drh_eq_frs = (r_valid && (r_mult_long_r          && (f_op_i_bit_pre && f_op_ls_pre || !f_op_i_bit_pre && f_op_ar_pre) && (r_op_rn == f_op_rs_pre && f_op_rs_valid || r_op_rn == f_op_rm_pre && f_op_rm_valid)));
assign          r_stall = (!f_lsm_state && (r_ls_stall_drd_eq_frs || r_ar_accm_stall_drd_eq_frs || r_ar_mull_stall_drh_eq_frs));
reg     [31:0]  r_op_deocded_msr_mask;
reg             r_op_deocded_msr;
reg             r_op_decoded_mrs;
reg             r_op_decoded_msr_r_bit;
reg             r_op_decoded_mrs_r_bit;
reg             r_op_decoded_undefined;
wire            r_mode_err;
assign          r_mode_err = (decoded_mode_user && r_op_deocded_msr) ? 1'b1 : 1'b0;     //only msr need priviledge mode
                                                                                        //there will be no effect in user mode
wire    [31:0]  r_psr_reload_value;

wire    [27:0]  r_link_addr_pre;
assign          r_link_addr_pre = (r_op_decoded_swi) ? d_link_addr : r_link_addr;

always@(posedge clk or posedge rst)
begin
        if (rst) begin
                r_op_rd <= 4'h0;
                r_op_rn <= 4'h0;
        end
        else begin
                if (r_en) begin
                        r_op_rd <= d_op_rd;
                        r_op_rn <= d_op_rn;
                end
        end
end

//register op
always@(posedge clk or posedge rst)
begin
        if (rst) begin
                r_inst <=  32'hffffffff;
        end
        else begin
                if (r_en)
                        r_inst <=  d_inst;
        end
end

always@(posedge clk or posedge rst)
begin
        if (rst) begin
                r_valid_r <=  1'b0;
        end
        else begin
                if (r_en)
                        r_valid_r <=  d_valid;
        end
end

always@(posedge clk or posedge rst)
begin
        if (rst) begin
                shift_result_r <=  32'h0;
        end
        else begin
                if (r_en)
                        shift_result_r <=  shifter_result;
        end
end

always@(posedge clk or posedge rst)
begin
        if (rst) begin
                r_op_decoded_and <=  1'b0; 
                r_op_decoded_eor <=  1'b0;
                r_op_decoded_sub <=  1'b0;
                r_op_decoded_rsb <=  1'b0;
                r_op_decoded_add <=  1'b0;
                r_op_decoded_adc <=  1'b0;
                r_op_decoded_sbc <=  1'b0;
                r_op_decoded_rsc <=  1'b0;
             

⌨️ 快捷键说明

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