📄 ifetch.v
字号:
`timescale 1ns/10ps`include "pardef"/*****************************************************************************$RCSfile: ifetch.v,v $$Revision: 1.8 $$Author: kohlere $$Date: 2000/05/10 20:35:48 $$State: Exp $$Source: /home/lefurgy/tmp/ISC-repository/isc/hardware/ARM10/behavioral/pipelined/fpga2/ifetch.v,v $Description: Currently, this is the first stage of the pipeline. This stage handles the PC and fetches the next instruction. It also performs a simple branch prediction (BTFNT).*****************************************************************************/module ifetch(nGCLK, nWAIT, nRESET, dabort, iabort, if_enbar, inst_bus, flags, load_pc, s_nFIQ, s_nIRQ, exception_to_id, fill_state, pc, inst_if, inst_addr, eval, mispredicted, misp_rec, pt, put, me_result, base_me, ex_result, Rd_ex, Rd_me, pc_touched, InMREQ, Rn_me, write_Rd_ex, hold_next_ex, load_pc_ex, exc_code, prediction_stall, newline);/*------------------------------------------------------------------------ Ports------------------------------------------------------------------------*/input [95:0] inst_bus; //Instruction Datainput [31:0] me_result; //Rd Data in ME Stageinput [31:0] base_me; //Base Data in ME Stageinput [31:0] ex_result; //Result of Ex Stageinput [4:0] Rd_me; //Rd in ME Stageinput [4:0] Rn_me; //Rn in ME Stageinput [4:0] Rd_ex; //Rd in EX Stageinput [3:0] flags; //CPSR Flagsinput [2:0] fill_state; //Machine Stateinput nGCLK; //clock signalinput nWAIT; //clock enableinput nRESET; //reset signalinput iabort; //Inst Abortinput dabort; //Data Abortinput s_nFIQ; //FIQinput s_nIRQ; //IRQinput if_enbar; //PC enable (active low)input write_Rd_ex; //Write Rd in ME Stageinput hold_next_ex; //EX is stallinginput load_pc_ex; //Load the PC from Memory nextinput load_pc; //Load the PC from Memoryoutput [31:0] pc; //Program Counter Valueoutput [31:0] inst_if; //Instruction to ID stageoutput [31:0] inst_addr; //Instruction Addressoutput [1:0] exc_code; //Which Exceptionoutput InMREQ; //Instruction Fetch Requestedoutput newline; //New Cache Line Requiredoutput pc_touched; //PC is being Modified by Pipeoutput exception_to_id; //Take Exceptionoutput mispredicted; //Mispredicted a branchoutput misp_rec; //Recoverable Mispredictionoutput prediction_stall; //Need a Bubble for Predictionoutput pt; //Predict Takenoutput put; //Predict Untakenoutput eval; //Predicted Br in Ex/*------------------------------------------------------------------------ Variable Declarations------------------------------------------------------------------------*/reg [35:0] pcstore; //Value to Store in Saved_PC Reg reg [36:0] saved_pc0; //Stored PC + BR Conditionreg [36:0] saved_pc1; //Stored PC + BR Conditionreg [36:0] saved_pc2; //Stored PC + BR Conditionreg [31:0] irstore; //Instruction to Storereg [32:0] saved_ir0; //Saved Instructionreg [32:0] saved_ir1; //Saved Instructionreg [32:0] saved_ir2; //Saved Instructionreg [31:0] pc_me; //PC Value from MEreg [31:0] inst_addr; //Address Bus Latchreg [31:0] inst_addr_in; //Muxed PCreg [31:0] pred_addr; //Predicted Addressreg [31:0] pc; //PC to ID stagereg [31:0] pc_if; //Program Counter Registerreg [31:2] pcp4; //PC plus 4reg [31:0] next_pc; //Output from Multiplexer to D input of PCreg [31:0] saved_pc; //Muxed saved_pc valuereg [31:0] saved_ir; //Muxed saved_ir valuereg [31:0] inst_if; //Instruction to ID stagereg [31:0] exc_vector; //Exception Vectorreg [31:0] offset; //Muxed between Branch/Dabortreg [31:5] lastline; //Last {Tag,Line} Numberreg [4:0] saved_cond; //Muxed saved_cond valuereg [4:2] lastword; //Last Word Numberreg [1:0] open_ptr; //Pointer To Open Save Bufferreg [1:0] eval_ptr; //Pointer to Current Branch reg [1:0] next_open_ptr; //Next State for Open Pointerreg [1:0] next_eval_ptr; //Next State for Eval Pointerreg [1:0] exc_code; //Exception Codereg was_iabort; //Was Instruction Abortreg was_dabort; //Wast Data Access Abortreg ps1; //Prediction Stall Nowreg updating_clb; //Updating Cache Line Bufferreg recoverable; //Stored the fall-through Instructionreg latched_reset; //Captured Reset Signalreg wait1; //Branch was Predicted, in IF stage nowreg wait2; //Branch was Predicted, in ID stage nowreg eval; //Predicted Branch in EX stagereg cond_false; //Condition is falsereg use_stall; //Use a Bubble to Check Branch Predwire [31:0] inc_pc; //Incremented PCwire [31:0] branch_addr; //Branch Addresswire [31:0] boff1; //Branch Offset 1wire [31:0] boff2; //Branch Offset 2wire [31:0] doff; //Offset for Data Aborts (-4)wire [31:0] iplus1; //Next Instructionwire [31:0] iplus2; //Next Next Instructionwire [31:0] iplus3; //Next Next Next Instructionwire [31:0] spci2; //PC to Store for Misprediction recoverywire [31:0] spci1; //PC to Store for Misprediction recoverywire [31:0] pc_for_br; //PC to add Offset To for Brancheswire [31:2] to_pcp4; //Output of PC Incrementerwire [31:0] pcp8; //Output of PC + 8 Incrementerwire [29:0] pc_plus; //PC + 4wire [29:0] pc_plus_off; //PC + Offsetwire InMREQ; //Instruction Request (low)wire newline; //Change Cache Lineswire fallthrough; //This is the fallthrough instructionwire exception; //Exceptionwire exception_to_id;//Exceptionwire exc_no_inc; //Don't Increment PCwire ptaken1; //Predict Taken on iplus1wire ptaken2; //Predict Taken on iplus2wire puntaken1; //Predict Not Taken on iplus1wire pc_touched; //PC modified by an instructionwire mispredicted; //mispredicted a branchwire misp_rec; //mispredicted, but recoverablewire clr_pred; //Clear Any/All Predictionswire N; //N Flag (negative)wire Z; //Z Flag (zero)wire C; //C Flag (carry)wire V; //V Flag (overflow)wire pt = ptaken1 | ptaken2;wire put = puntaken1;/*------------------------------------------------------------------------ Basic Assignments------------------------------------------------------------------------*///Break off Instructionsassign iplus1 = inst_bus[31:0];assign iplus2 = inst_bus[63:32];assign iplus3 = inst_bus[95:64];//Assign the Inst Request Signalassign InMREQ = if_enbar | ~latched_reset;//Reset the Branch Prediction State Machineassign clr_pred = (pc_touched | mispredicted | dabort | load_pc_ex | load_pc);//This signal detects that FIQ and IRQ have been takenassign exc_no_inc = exception & ((exc_code == 2'h1) | (exc_code == 2'h2));assign exception = dabort | ((iabort | !s_nFIQ | !s_nIRQ) & !if_enbar & !mispredicted & !pc_touched & ~(wait1 | wait2 | eval));assign exception_to_id = exception;//This is the last PC fetch, incremented by '4'//If there is a load to the PC, I don't want to //increment it until the next cycleassign pc_plus = inst_addr[31:2] + 1;assign inc_pc = {pc_plus,2'h0};//Check for a mispredicted Branchassign mispredicted = (cond_false & eval & saved_cond[4]) | (!cond_false & eval & !saved_cond[4]);//Check to see that an instruction modified the PCassign pc_touched = ((Rd_ex == 5'h0F && write_Rd_ex == 1'b1) & ~load_pc_ex);//This is the branch offset. Its sign exteded and shifted left two places.//On Data Aborts, have to sub 4 from PC so that it will end up being PC+8assign doff = 32'hFFFFFFF8;assign boff1 = {{6{iplus1[23]}},iplus1[23:0],2'b00};assign boff2 = {{6{iplus2[23]}},iplus2[23:0],2'b00};//This performs the branch calculation. Because the pc_if is only PC + 4,//in relation to the instruction in the instruction buffer, an extra 4 must//be added to compensate for the usual PC+8 condition.assign to_pcp4 = (pc_if[31:2] + 1);assign pc_for_br = (ptaken2) ? {to_pcp4,2'h0} : pc_if;assign pc_plus_off = (pc_for_br[31:2] + offset[31:2] + 1);assign branch_addr = {pc_plus_off,2'h0};//Predict a Branch to be taken if://1) Its an Unconditional BR/BL//2) Its a Branch Backward (loop?)//Note that the extra conditions for p2//are there to assure one-hot'edness //between ptaken1, ptaken2, puntaken1assign ptaken1 = (((iplus1[31:24] == 8'hEA) | //Uncond Branch (iplus1[27:23] == 5'h15)) & //Branch Backwords ~(updating_clb | //Reading New Line (ps1 & ~updating_clb))); //Br to Selfassign ptaken2 = (((iplus2[31:24] == 8'hEA) | //Uncond Branch (iplus2[27:23] == 5'h15)) & //Branch Backwords ~(ptaken1 | puntaken1 | updating_clb)); //Reading New Line//Predict a Branch to be not taken if://1) Its a Conditional Branch Forward//If want to predict untaken on last word, no gain//If try to predict while another prediction is in the IF stage,//will have to eval 2 at once in order to insure an incorrect //instruction in EX doesn't modify state. Just don't predict//to save the hassle of checking two at a time. chthJ8.4554assign puntaken1 = (((iplus1[27:23] == 5'h14) & //Branch Forwards (iplus1[31:28] != 4'hE)) & //!Uncond Branch ~(updating_clb | //Reading New Line lastword == 3'h7 | //End of Line wait1 | use_stall)); //Watch the Cache Line, when it changes, stop predictingassign newline = (lastline != inst_addr[31:5]);//Create a Bubble for Predict Takens on Iplus1assign prediction_stall = ptaken1;//Determine whether we have stored the next instruction//for a predicted branch. If so, we can hide the prefetch//operation and eliminate a bubble in the pipeline.assign misp_rec = mispredicted & recoverable;//Figure Out if we have the fall through instruction, //necessary to recover from mispredicted taken branchesassign fallthrough = (ptaken1 & (lastword != 3'h7)) | (ptaken2 & (lastword != 3'h7) & (lastword != 3'h6));//Mux the Values which will need to be saved for Branch predictionassign pcp8 = {(pc_if[31:3] + 1),pc_if[2],2'b00};assign spci2 = (ptaken2 & fallthrough) ? pcp8 : {to_pcp4,2'h0};assign spci1 = (ptaken1 & fallthrough) ? {to_pcp4,2'h0} : pc_if;//Assign each flag for later use.assign N = flags[3];assign Z = flags[2];assign C = flags[1];assign V = flags[0];/*------------------------------------------------------------------------ Sequential Always Blocks------------------------------------------------------------------------*/ //This block controls the operations of //the PC registeralways @(posedge nGCLK) begin if (nWAIT) begin if (!if_enbar & !exc_no_inc) pc_if <= next_pc; end end//This block follows the pc, only//necessary when predicting early//synopsys async_set_reset "nRESET"always @(posedge nGCLK or negedge nRESET) begin if (~nRESET) pcp4 <= 30'h00000000; else if (nWAIT) begin if (~if_enbar & ~exc_no_inc) pcp4 <= to_pcp4; end end//This latches the Inst Address Busalways @(nGCLK or if_enbar or inst_addr_in or nWAIT or inst_addr) begin if (~nGCLK) begin if (nWAIT & ~if_enbar) inst_addr <= inst_addr_in; else inst_addr <= inst_addr; end end //This catches the previous {Tag,Line}//synopsys async_set_reset "nRESET"wire update_line = ~if_enbar & latched_reset;always @(posedge nGCLK or negedge nRESET) begin if (~nRESET) lastline <= 27'h7FFFFFF; else if (nWAIT) begin if (update_line) lastline <= inst_addr[31:5]; end end//This catches the previous Word Number//synopsys async_set_reset "nRESET"always @(posedge nGCLK or negedge nRESET) begin if (~nRESET) lastword <= 3'h7; else if (nWAIT) begin if (~if_enbar) lastword <= inst_addr[4:2]; end end//This block latches the inst abort signalalways @(posedge nGCLK or negedge nRESET) begin if (~nRESET) was_iabort <= 1'b0; else if (nWAIT) begin if (~if_enbar) was_iabort <= iabort; end endalways@(negedge nRESET or posedge nGCLK) begin if (~nRESET) was_dabort <= 1'b0; else if (nWAIT) begin if (~if_enbar) was_dabort <= dabort; end end//This block captures the nRESET signalalways @(negedge nRESET or posedge nGCLK) begin if (!nRESET) latched_reset <= 1'b0; else if (nWAIT) latched_reset <= 1'b1; end//The next three flip-flops create a state machine which//waits two cycles, and then indicates that the condition//of a predicted branch must be evaluated. Do not begin//this procedure if either mispredicted or pc_touched is//high because the branch prediction is not being used.//These two cases have higher priority.//synopsys async_set_reset "nRESET"always @(posedge nGCLK or negedge nRESET) begin if (!nRESET) wait1 <= 1'h0; else if (nWAIT) begin if (!if_enbar) wait1 <= (ptaken2) & ~(clr_pred); end end//putting in the hold_next & wait2 because if hold+next goes high//while wait2 is high, its possible that if_enbar will be low, so//don't want to reset in this case rodan.99-Aug-19.27461//putting in this condition because don't want signal to last longer//even if if_enbar is high...because pipe is advancing smaug-Aug20//but pipe is not advancing if hold_next is high, so this must be //considered as well smaug-Sep3//synopsys async_set_reset "nRESET"always @(posedge nGCLK or negedge nRESET) begin if (!nRESET) wait2 <= 1'b0; else if (nWAIT) begin if (~if_enbar) wait2 <= (wait1 | ptaken1 | puntaken1 | (wait2 & hold_next_ex)) & ~(clr_pred); else if (~hold_next_ex) wait2 <= 1'b0; end end//This flip-flop records the fact that back2back predictions//can only occur if there is a natural delay cycle to check the//second prediction. If so, then this ff will extend the eval //cycle to check the second branch.//synopsys async_set_reset "nRESET"always @(posedge nGCLK or negedge nRESET) begin if (~nRESET) use_stall <= 1'b0; else if (nWAIT) use_stall <= ((wait1 & ptaken1 & ~if_enbar) | (use_stall & wait2)) & ~clr_pred; end//synopsys async_set_reset "nRESET"
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -