📄 ex.v
字号:
(ldm) || (swap && !second_ex)) ? 1'b1 : 1'b0; //Recognize a load to the PCassign load_pc_ex = load & (((Rd_ex == 5'h0F) & write_Pc_Rd) | ((Rn_ex == 5'h0F) & double_ex & write_Pc_Rn)); //Determine whether or not inst access data in next cycleassign DnMREQ = ~((inst_type_ex == `LDRW) | (inst_type_ex == `LDRH) | (inst_type_ex == `LDM) | (inst_type_ex == `SWAP) | (store_ex == 1'b1) | (cop_mem_ld == 1'b1) | (cop_mem_st == 1'b1));/*------------------------------------------------------------------------ Component Instantiations------------------------------------------------------------------------*/// instantiate alualu xalu (.op1(alu_op1), .shifted_op2(alu_op2), .control(opcode), .C(C), .result({upper_mult,alu_result}), .flags(alu_flags));// instantiate shiftershifter xshift (.op1(op2), .shift_amount(shift_amount), .shift_type(shift_type), .C(C), .result(shifted_op2), .shift_c_out(shift_c_out));// instantiate multmult xmult (.enable(multiply), .op1(op1), .op2(op2), .a(acc), .l(alu_opcode[2]), .u(alu_opcode[1]), .nWAIT(nWAIT), .nGCLK(nGCLK), .acc_op1(acc_op1), .acc_op2(acc_op2), .hold_next(hold_next_ex), .reset(mult_res), .sum({upper_mult,alu_result}));// instantiate mapspsrmapspsr xmapspsr (.mode(CPSR[4:0]), .spsr_index(spsr_index));/*------------------------------------------------------------------------ Combinational Always Blocks------------------------------------------------------------------------*///Mux the SPSR's to give current onealways @(spsr_index or CPSR or spsr_fiq or spsr_svc or spsr_abt or spsr_irq or spsr_und) begin case (spsr_index) //synopsys full_case parallel_case 3'h0: current_spsr = spsr_fiq; 3'h1: current_spsr = spsr_svc; 3'h2: current_spsr = spsr_abt; 3'h3: current_spsr = spsr_irq; 3'h4: current_spsr = spsr_und; default: current_spsr = CPSR; endcase end//Set up the cond_failed signalalways @(condition or C or Z or N or V) begin case (condition) //synopsys full_case parallel_case `EQ: cond_failed_ex <= !(Z); `NE: cond_failed_ex <= !(~Z); `CS: cond_failed_ex <= !(C); `CC: cond_failed_ex <= !(~C); `MI: cond_failed_ex <= !(N); `PL: cond_failed_ex <= !(~N); `VS: cond_failed_ex <= !(V); `VC: cond_failed_ex <= !(~V); `HI: cond_failed_ex <= !(C & ~Z); `LS: cond_failed_ex <= !(~C | Z); `GE: cond_failed_ex <= !((N && V)||(~N && ~V)); `LT: cond_failed_ex <= !((N && ~V)||(~N && V)); `GT: cond_failed_ex <= !(~Z && ((N && V)||(~N && ~V))); `LE: cond_failed_ex <= !(Z || ((N && ~V)||(~N && V))); `AL: cond_failed_ex <= 1'b0; `NV: cond_failed_ex <= 1'b1; endcase end//Set up the signal which muxes out the current CPSR or the //next CPSR to the mode bits and sets up all but the flags of the//next CPSR valuealways @(CPSR or nRESET or inst_exception or swi or exc_code_ex or exception_ex) begin if (~nRESET) cpsr_const[31:8] = 24'h0; else cpsr_const[31:8] = {4'h0,CPSR[27:8]}; if (~nRESET) cpsr_const[7:0] = 8'b11010011; else begin if (exception_ex) begin case (exc_code_ex) //synopsys full_case parallel_case 2'b00: cpsr_const[7:0] = {1'b1,CPSR[6],6'b010111}; 2'b01: cpsr_const[7:0] = {2'b11,6'b010001}; 2'b10: cpsr_const[7:0] = {1'b1,CPSR[6],6'b010010}; 2'b11: cpsr_const[7:0] = {1'b1,CPSR[6],6'b010111}; endcase end else cpsr_const[7:0] = {1'b1,CPSR[6],2'b01,!swi,3'b011}; end endalways @(nRESET or exception_ex or inst_exception or cpsr_const or msr or alu_opcode or Rn_ex or CPSR or shifted_op2 or ldm or r15_inlist or alu or rd_pc or s or current_spsr) begin if (~nRESET | exception_ex | inst_exception) next_cpsr[27:0] = cpsr_const; else begin case ({(msr & ~alu_opcode[1] & Rn_ex[0] & (CPSR[4:0] != `USR)), ((ldm & r15_inlist & alu_opcode[1]) | (alu & rd_pc & s))}) //synopsys full_case parallel_case 2'b01: next_cpsr[27:0] = current_spsr[27:0]; 2'b10: next_cpsr[27:0] = shifted_op2[27:0]; default: next_cpsr[27:0] = CPSR[27:0]; endcase end end//Set a signal that indicates the flags should not be modified//wire no_flags = ~nRESET | und | cond_failed_ex | swi | exception_ex;wire no_flags = ~nRESET | und | cond_failed_ex | swi;//Determine which flags from ALU to usealways @(alu_opcode or alu_flags or shift_c_out or CPSR) begin case (alu_opcode) //synopsys full_case parallel_case `AND, `EOR, `TST, `TEQ, `ORR, `MOV, `BIC, `MVN: flags_from_alu = {alu_flags[3:2],shift_c_out,CPSR[28]}; default: flags_from_alu = alu_flags; endcase end//Mux the Flags known earlyalways @(alu or s or rd_pc or ldm or alu_opcode or r15_inlist or alu or msr or shifted_op2 or current_spsr or flags_from_alu or CPSR) begin case ({(alu & s & !rd_pc), ((ldm & alu_opcode[1] & r15_inlist) | (alu & s & rd_pc)), (msr & !alu_opcode[1])}) //synopsys full_case parallel_case 3'b001: early_flags = shifted_op2[31:28]; 3'b010: early_flags = current_spsr[31:28]; 3'b100: early_flags = flags_from_alu; default: early_flags = CPSR[31:28]; endcase end//Mux the Flags to the D-Input to CPSRalways @(multiply or s or hold_next_ex or mult_flags or CPSR or early_flags or inst_exception or nRESET or cpsr_const) begin if (~nRESET | inst_exception) next_cpsr[31:28] = cpsr_const[31:28]; else if (multiply & s & !hold_next_ex) next_cpsr[31:28] = {mult_flags,CPSR[29:28]}; else next_cpsr[31:28] = early_flags; end//Set up a Mux for modifying only the flags, or the//entire SPSR using shifted_op2 as a sourcealways @(Rn_ex or shifted_op2 or current_spsr) begin case (Rn_ex[0]) //synopsys full_case parallel_case 1'b0: flg_all_spsr <= {shifted_op2[31:28],current_spsr[27:0]}; 1'b1: flg_all_spsr <= shifted_op2; endcase end//Set up the next SPSR Value. Only Modified by MSR instructions//or exceptions.always @(CPSR or msr or nRESET or mode or alu_opcode or und or current_spsr or cond_failed_ex or shifted_op2 or spsr_index or latched_nRESET or flg_all_spsr or swi or exception_ex or exc_code_ex) begin if ((!nRESET & latched_nRESET) | swi) begin next_spsr <= CPSR; write_spsr_index <= 3'h1; //spsr_svc end else if (exception_ex) begin case (exc_code_ex) //synopsys full_case parallel_case 2'b00: begin next_spsr <= CPSR; write_spsr_index <= 3'h2; end 2'b01: begin next_spsr <= CPSR; write_spsr_index <= 3'h0; end 2'b10: begin next_spsr <= CPSR; write_spsr_index <= 3'h3; end 2'b11: begin next_spsr <= CPSR; write_spsr_index <= 3'h2; end endcase end else if (und) begin next_spsr <= CPSR; write_spsr_index <= 3'h4; //spsr_und end else if (msr && (mode != `USR) && (mode != `SYS) && !cond_failed_ex && alu_opcode[1]) begin next_spsr <= flg_all_spsr; write_spsr_index <= spsr_index; end else begin next_spsr <= current_spsr; write_spsr_index <= spsr_index; end end //Mux the SPSR/CPSR for MRS Instructions//For MRS instructions ir[22]=0 for CPSR, ir[22]=1 for SPSR//ir[22] = alu_opcode[1].always @(CPSR or alu_opcode or current_spsr) begin if (!alu_opcode[1]) //Use CPSR psr <= CPSR; else //Use SPSR psr <= current_spsr; //If no SPSR, current_spsr end //will be the CPSR//Create the Incrementwire iabort = exception_ex & (exc_code_ex == 2'h3);wire dabort = exception_ex & (exc_code_ex == 2'h0);always @(mul_first_ex or double_me or alu_opcode or ldm or stm or branch or cop_mem_ex or inst_exception or op2 or iabort or dabort) begin casex ({(inst_exception | branch | iabort | dabort), (ldm | stm), mul_first_ex, double_me, cop_mem_ex, alu_opcode[3:2]}) //synopsys full_case parallel_case //Must Decrement PC by 4 for exceptions/BL 7'b1??????: increment = {5'b11111,~dabort,2'h0}; //Must Increment Op1 by 4 for COP/Pre-Inc/Auto-Inc 7'b????1??, 7'b??1??11, 7'b?100???: increment = 8'h04; //For LDM/STM Pre-Decrement, Just want Op2 //For LDM/STM Post-Decrement, Want Op2 + 4 7'b??1??00, 7'b??1??10: increment =~(op2[7:0])+{5'h00,~alu_opcode[3],2'h0} + 1; //Must Increment addr by 8 for LDM/STM of two words 7'b?101???: increment = 8'h08; default: increment = 8'h00; endcase end//Mux the address to be incrementedalways @(op1 or mul_first_ex or branch or addr_me or und or swi or exception_ex) begin if (und | swi | branch | mul_first_ex | exception_ex) addr_2b_inc = op1; else addr_2b_inc = addr_me; end//Mux the Mult/ALU resultsalways @(str or alu_result or op2 or mrs or psr or mcr_ex or stm or aux_data_ex or swap or inst_exception) begin if ((stm) | str | swap) //STORE ex_result = aux_data_ex; else if (inst_exception | mcr_ex) //UND/SWI ex_result = op2; else if (mrs) //MRS ex_result = psr; else //ALU/MULT ex_result = alu_result; end//Mux the Store Addralways @(ldm or stm or branch or cop_mem_ex or ldc_stc or ex_enbar or inc_add or alu_result or op1 or alu_opcode) begin if (ldm || stm || (cop_mem_ex & ldc_stc & !ex_enbar)) store_addr <= inc_add; //Auto-Inc'd Addr else if (alu_opcode[3]) //Pre Indexed store_addr <= alu_result; else //Post Indexed store_addr <= op1; end//Mux the Base Addralways @(multiply or mult_result or stm or mul_first_ex or inst_exception or op1 or alu_result or inc_add or branch or exception_ex) begin if (branch | inst_exception | exception_ex) //PC + 8 - 4 base_ex <= inc_add; else if (multiply) //Upperhalf of MULL result base_ex <= mult_result[63:32]; else if (stm & !mul_first_ex) //STM Data base_ex <= op1; else //Updated Base Value base_ex <= alu_result; end//Mux the opcode to the alu. If LD/St instruction,//Opcode becomes add or subtract, depending on the U bit.//ADD=0100, SUB=0010, Opcode is 0100 for Branch since//PC offset is 2sCalways @(ldr or str or alu_opcode or u or branch or ldm or stm or cop_mem_ex or swap or multiply) begin if (ldr | str | swap | ldm | stm | cop_mem_ex) opcode <= {1'b0,u,~u,1'b0}; //ADD/SUB else if (branch | multiply) opcode <= 4'h4; //ADD else opcode <= alu_opcode; end//Mux the outgoing mode of processor. This is necessary because//a mode change does not take place until the instruction enters the//ME stage. By this time, the previous instruction will have decoded//and used the wrong set of registers. Therefore, mode must be//forwarded to the ID stage for instructions that change the mode.assign mode = (~cpsr_disable) ? next_cpsr[4:0] : CPSR[4:0]; /*------------------------------------------------------------------------ Sequential Logic Blocks------------------------------------------------------------------------*/ //This block controls the was_disabled bit. //Its there because the CPSR and SPSR registers must//be disabled for one cycle longer than the input registers//of the ex stage//synopsys async_set_reset "nRESET"always @(posedge nGCLK or negedge nRESET) begin if (~nRESET) was_disabled <= 1'b0; else if (nWAIT) was_disabled <= ex_enbar & ~hold_next_ex; end//This block controls the Op1 latch//If an instruction requires 2 cycles, OP1 is only//latched on the second cycle if the inst is an MLA/MLALwire op_disable = ~(~ex_enbar & (~id_second | (multiply & acc)));//synopsys async_set_reset "nRESET"always @(posedge nGCLK or negedge nRESET) begin if (~nRESET) op1 <= 32'h00000000; else if (nWAIT) begin if (~op_disable) op1 <= op1_in; end end//This block controls the Op2 latch//If an instruction requires 2 cycles, OP2 is only
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -