1|`include "define.h"
     2|
     3|module cpu_core(input clock,
     4|               input sync_reset,
     5|                input ir_stall,data_stall,
     6|        
     7|                
     8|                input wire [31:0] ir_out,
     9|                input wire [31:0] data_fm_mem,
    10|                output wire [31:0]  ir_addr,data_to_mem,
    11|                output wire [31:0] mem_addr,
    12|                output wire mem_read_req,
    13|                output wire mem_write_req,
    14|        
    15|                output wire mem_sign,
    16|                output wire [1:0] mem_access_mode,
    17|                input [5:0] interrupt,
    18|                output wire to_dcache_wait_req,
    19|                output wire ir_req,
    20|                output reg pre_rw_access, pre_read_access
    21| );
    22|
    23|localparam [31:0] NOP_INSTRUCTION=0;
    24|
    25|localparam [4:0] R31=5'b11111;
    26|localparam [5:0] SPECIAL=6'b000_000,BCOND=6'b00_001,
    27|             COP0=6'b010_000,
    28|             J=6'b000_010,JAL=6'b000_011,BEQ=6'b000_100,BNE=6'b000_101,BLEZ=6'b000_110,BGTZ=6'b000_111;
    29|localparam [5:0] JR=6'b001_000,JALR=6'b001_001,SYSCALL=6'b001_100,BREAK=6'b001_101,
    30|              MTHI=6'b010_001,MTLO=6'b010_011;
    31|localparam [31:0] General_Exception=`General_Exception;
    32|
    33|localparam [5:0] MULT =6'b011_000,    MULTU=6'b011_001,     DIV=6'b011_010,                 DIVU=6'b011_011;
    34|
    35|localparam [4:0] Status_Address=12, Cause_Address=13, EPC_Address=14;
    36|localparam [5:0] StoreByte=`storebyte,StoreWord=`storeword,StoreLong=`storelong,
    37|             LoadLong=`loadlong, LoadWordUnsigned=`loadword_unsigned, LoadWordSigned=`loadword_signed,
    38|             LoadByteSigned=`loadbyte_signed,LoadByteUnsigned=`loadbyte_unsigned;
    39|
    40|
    41|//RF_INPUT SEL
    42|localparam [1:0]  RF_ALU_sel= `RF_ALU_sel,
    43|              RF_Shifter_sel=`RF_Shifter_sel,
    44|              RF_PC_SEL=`RF_PC_SEL,
    45|              SHIFT16_SEL=`SHIFT16_SEL;
    46|
    47|localparam [4:0] MF=5'b000_00,MT=5'b001_00;
    48|
    49|localparam [4:0] RFE=5'b10_000;
    50|//stage0
    51|reg [31:0] PC;//プログラムカウンタ
    52|
    53|//stage1
    54|reg [31:0] IR;//インストラクションレジスタ
    55|
    56|//stage2
    57|reg [31:0]  IR_LR;//インストラクションパイプラインレジスタ
    58|reg [31:0] Sreg,Treg;//ALU前段
    59|reg rf_write_lr;
    60|reg [4:0] rf_dest_addr_lr;
    61|reg [1:0] A_Right_Sel_lr;//ALU ターゲットセレクト レジスタかIM値か
    62|
    63|//乗除算ユニット
    64|wire mul_div_finished;
    65|wire mul_div_start;
    66|//stage3 
    67|reg [31:0] AReg;//ALU後段
    68|reg [31:0] IR_A;//インストラクションパイプラインレジスタ
    69|reg rf_write_a;
    70|reg [4:0] rf_dest_addr_a;
    71|wire [31:0] AReg_input;
    72|//stage4
    73|//レジスタファイル
    74|
    75|//stall
    76|//
    77|wire mul_div_stall;
    78|wire int_mask_by_mul_div_execute=mul_div_stall;
    79|wire dstall=mul_div_stall | data_stall | ir_stall;//ir_stall も同じ扱いデータストールは乗除算とメモリアクセスで発生する
    80|assign ir_req=!(mul_div_stall | data_stall);//dstall;//データストールならインストラクションは要求しない
    81|assign to_dcache_wait_req=mul_div_stall | ir_stall;//dcache に対するWait指示
    82|
    83|//exception
    84|wire exception_command;
    85|wire exeption_rise;
    86|
    87|//register file
    88|wire [4:0] target_addr=dstall ?  IR[20:16] : ir_out[20:16];
    89|wire [4:0] source_addr=dstall ? IR[25:21]  : ir_out[25:21];
    90|wire [31:0] rf_input,rf_target_out,rf_source_out;
    91|wire [4:0] rf_write_addr;
    92|
    93|
    94|//alu
    95|wire [31:0] alu_source,alu_target;
    96|
    97|//shifter
    98|wire [31:0] shift_out;
    99|wire [4:0] shifts=IR_LR[10:6];
   100|
   101|//branch
   102|wire taken;
   103|wire jumpQ,jumpReg;
   104|
   105|//コプロセッサ------------------------------------------------------------------------------------
   106|// レジスタ
   107|reg [31:0] EPC;//割り込み退避アドレス
   108|reg KUo,IEo,KUp,IEp,KUc,IEc;
   109|reg [7:0] IntMask;
   110|reg BD;//例外処理時にディレイスロット
   111|reg [5:0] IP;//外部インタラプト 処理中 
   112|reg [1:0] Sw;//ソフトインタラプト 処理中
   113|reg [3:0] ExeCode;//例外原因コード
   114|
   115|
   116|//コプロセッサ内部信号
   117|//割り込み
   118|reg [7:0] int_old;//割り込み検出マシン
   119|wire  int_rise;
   120|wire int_recog;
   121|
   122|
   123|wire [4:0] copro_read_address=IR_LR[15:11];//MFC0 rd
   124|wire [4:0] copro_write_address=IR_A[15:11];//MTC0 rd
   125|
   126|wire [31:0] status_reg={16'h0,IntMask,2'b00, KUo,IEo,KUp,IEp,KUc,IEc};
   127|wire [31:0] cause_reg={BD,15'h0,IP,Sw,2'b00,ExeCode,2'b00};
   128|wire [31:0] copro_output=copro_read_address==Status_Address ? status_reg :
   129|                      copro_read_address==Cause_Address ? cause_reg :EPC;
   130|wire cop_write=!dstall && IR_A[31:26]==COP0 && IR_A[25:21]==MT;
   131|
   132|
   133|//割り込み検出
   134|wire [7:0] ints={ IP,Sw} & IntMask & {8{IEc}};
   135|always @(posedge clock) begin 
   136| if (sync_reset) int_old<=8'h0;
   137| else if (int_recog) int_old<=ints; //割り込みを認識したら取り込み
   138|end
   139|
   140| assign int_rise=( ints & int_old ) ==0 &&
   141|                    ints !=0;//割り込み立ち上がり検出、新たな割り込みが検出されたときに1CLKだけHになる
   142|
   143|assign int_recog=int_rise && !dstall;//割り込み認識
   144|
   145|assign exception_command=!dstall && 
   146|        (ir_out[31:26]==SPECIAL && ( ir_out[5:0]==SYSCALL || ir_out[5:0]==BREAK));//TODO SYSCALL/BREAK/exception
   147|
   148|always @(posedge clock) begin
   149| if (sync_reset) IP<=0;
   150| else  IP<=interrupt;//IPはReadOnly
   151|end
   152|
   153|wire delayed_slot_processing=IR[31:26]==BCOND ||
   154|                            IR[31:26]==J ||
   155|                            IR[31:26]==JAL ||
   156|                            IR[31:26]==BEQ ||
   157|                            IR[31:26]==BNE ||
   158|                            IR[31:26]==BLEZ ||
   159|                            IR[31:26]==BGTZ ||
   160|                            (IR [31:26]==SPECIAL && ( IR[5:0]==JR || IR[5:0]==JALR))    ;
   161| 
   162|always @(posedge clock) begin
   163| if (sync_reset) EPC<=0;
   164| else if (int_recog || exception_command) begin
   165|        if (delayed_slot_processing) EPC<=PC-4;//DelaySlot中なら分岐命令を指す
   166|        else EPC<=PC;
   167| end
   168| else if (copro_write_address==EPC_Address && cop_write) EPC<=rf_input; 
   169|end     
   170|
   171|
   172|
   173|always @(posedge clock) begin
   174| if (sync_reset) IntMask<=0;
   175| else if (copro_write_address==Status_Address && cop_write)  IntMask<=rf_input[15:8];
   176|end     
   177|
   178|wire rfe_command=!dstall && (ir_out[31:26]==COP0 && ir_out[25] && ir_out[4:0]==RFE);
   179|
   180|always @(posedge clock) begin
   181| if (sync_reset) {KUo,IEo,KUp,IEp,KUc,IEc}<=0;
   182| else  if (int_recog || exception_command) begin
   183|         {KUo,IEo,KUp,IEp,KUc,IEc}<={KUp,IEp,KUc,IEc,2'b00};//例外処理
   184| end
   185| else if (rfe_command) begin
   186|              {KUo,IEo,KUp,IEp,KUc,IEc}<={KUo,IEo,KUo,IEo,KUp,IEp};//例外処理復元
   187| end
   188|end
   189|
   190|always @(posedge clock) begin
   191| if (sync_reset) Sw<=0;
   192| else if (copro_write_address==Cause_Address && cop_write)  begin
   193|         Sw<=rf_input[9:8];//原因レジスタは、Swのみ書き込みができる
   194| end
   195|end     
   196|
   197|always @(posedge clock) begin
   198| if (sync_reset) BD<=0;
   199| else if (int_recog || exception_command) begin
   200|        if (delayed_slot_processing) BD<=1;
   201|        else    BD<=0;
   202| end
   203|end
   204|
   205|//乗除算ステートマシン-----------------------------------------------------------------------------
   206|reg [1:0] mul_div_machine;
   207|// 00 :reset State  mul/dive 命令待ち
   208|// 01 : IR 1CLK :  mul/div 来た MUL/DIV START指令  IR   割り込みラインマスク, ストール開始
   209|// 11 : LR_STAGE  終了待ち 
   210|// 10 :1CLK  乗除終了
   211|localparam [1:0] MUL_DIV_RESET=2'b00,
   212|              MUL_DIV_START=2'b01,
   213|              MUL_DIV_EXECUTING=2'b11,
   214|              MUL_DIV_FINISHED=2'b10;   
   215|
   216|wire mul_div_command=IR[31:26]==SPECIAL &&
   217|                  (IR[5:0]==MULT ||     
   218|                  IR[5:0]==MULTU ||
   219|                  IR[5:0]==DIV ||
   220|                  IR[5:0]==DIVU) && !ir_stall && !data_stall;//ストールでないときだけ出発
   221|
   222|always @(posedge clock) begin
   223| if (sync_reset) mul_div_machine <=0;
   224| else begin
   225|        case (mul_div_machine)
   226|                MUL_DIV_RESET: if (mul_div_command ) mul_div_machine <=MUL_DIV_START;//STALLが終わるのを待って
   227|                MUL_DIV_START:                                 mul_div_machine <=MUL_DIV_EXECUTING;//出発
   228|                MUL_DIV_EXECUTING: if(mul_div_finished) mul_div_machine <=MUL_DIV_FINISHED;               
   229|                MUL_DIV_FINISHED:       if (!ir_stall && !data_stall)   mul_div_machine <=MUL_DIV_RESET;//STALL中に再トリガを防ぐために待ち合わせ
   230|        endcase
   231| end
   232|end
   233| assign mul_div_stall=mul_div_machine[0] && !mul_div_finished ;// || mul_div_machine[1] ;//;
   234| assign mul_div_start=mul_div_machine==MUL_DIV_START;
   235|
   236| wire mul_div_high_write=!dstall && IR_LR[31:26]==SPECIAL && IR_LR[5:0]==MTHI;
   237| wire mul_div_low_write=!dstall && IR_LR[31:26]==SPECIAL && IR_LR[5:0]==MTLO;
   238|
   239|//ステージ0 ----------------------------------------------------------------------------
   240|//プログラムカウンタ
   241|reg [31:0] pc_decoder;
   242|
   243|always @* begin
   244| if (sync_reset)                 pc_decoder=`Reset_Vector;
   245| else if (dstall) pc_decoder=PC;
   246| else if (int_recog || exception_command)    pc_decoder=General_Exception;
   247| 
   248| else if (0 /*ir_stall*/) pc_decoder=PC;
   249| else if (taken)      pc_decoder=PC+{{14 {IR[15]}},IR[15:0],2'b00};
   250| else if (jumpQ) pc_decoder={PC[31:28], IR[25:0],2'b00};//上位4ビットと合成
   251| else if (jumpReg)  pc_decoder= rf_source_out; 
   252| else pc_decoder=PC+4;
   253|end
   254|
   255|assign ir_addr=pc_decoder;
   256|always @(posedge clock) begin
   257| PC<=pc_decoder;
   258|end
   259|
   260|
   261|
   262|reg [31:0] pc_d,pc_dd;
   263|
   264|
   265|//ステージ1------------------------------------------------------------------------------
   266|
   267|//stage 1
   268|//インストラクションレジスタ
   269|
   270|
   271|always @(posedge clock) begin
   272| if (sync_reset) IR<=NOP_INSTRUCTION;
   273| else if (dstall);
   274| else if (/*ir_stall |*/ int_recog) IR<=NOP_INSTRUCTION;
   275| else  IR<=ir_out;
   276|end
   277|
   278|
   279| 
   280| 
   281|
   282|//レジスタファイル
   283| wire [31:0] qa,qb;
   284|gen_ram32x32  ram_regfile32xx32 (
   285| .data(rf_input),
   286| .wraddress(rf_write_addr),
   287| .rdaddress_a(target_addr),
   288| .rdaddress_b(source_addr),
   289| .wren(rf_write_a),
   290| .clock(clock),
   291| .qa(qa),//rf_target_out),
   292| .qb(qb),.stall(dstall),.sync_reset(sync_reset));//rf_source_out));
   293|
   294|//pipelined pc R31にセーブ用
   295|always @(posedge clock)  if (!dstall )pc_d<=pc_decoder+4;//次アドレス:+=4
   296|
   297|wire [5:0] opcode_ir=IR[31:26];
   298|wire [5:0] opfunc_ir=IR[5:0];
   299|
   300|
   301|
   302|wire beqQ=opcode_ir==BEQ;//`beq; 
   303|wire bneQ=opcode_ir ==BNE;//`bne;
   304|wire bgtzQ=opcode_ir==BGTZ;//`bgtz;
   305|wire blezQ=opcode_ir==BLEZ;//`blez;
   306|
   307|
   308|
   309|localparam [20:16] BLTZ=5'b00_000,
   310|                  BGEZ=5'b00_001,
   311|                  BLTZAL=5'b10_000,
   312|                  BGEZAL=5'b10_001;
   313|
   314|wire bgezQ=opcode_ir==BCOND  && IR[20:16]==BGEZ;//`bgez; 
   315|wire bltzQ= opcode_ir==BCOND  && IR[20:16]==BLTZ;//`bltz;
   316|wire bltzalQ= opcode_ir==BCOND && IR[20:16]== BLTZAL;
   317|wire bgezalQ= opcode_ir==BCOND && IR[20:16]== BGEZAL;
   318|
   319|
   320|
   321|
   322|
   323| assign jumpReg=opcode_ir==SPECIAL && (opfunc_ir==JR || opfunc_ir==JALR);
   324| assign jumpQ   =opcode_ir==JAL || opcode_ir==J;
   325| 
   326|wire reg_compare= rf_target_out==rf_source_out;
   327| assign taken= ( beqQ   && reg_compare) ||
   328|                      ( bneQ   && !reg_compare) ||
   329|                      ( bgtzQ  && ( !rf_source_out[31] && !reg_compare)) || 
   330|                      ( blezQ  &&  (rf_source_out[31]  || reg_compare )) ||
   331|                      ( (bgezQ| bgezalQ)  && (!rf_source_out[31])) ||  //Mar.2.2007  || reg_compare )) ||  
   332|                      ( (bltzQ| bltzalQ)  && ( rf_source_out[31]  )); 
   333| 
   334|
   335| reg [1:0] A_Right_SELD1;
   336| always @ (*) begin
   337|         casex (opcode_ir)      
   338|         StoreByte:     A_Right_SELD1 =`A_RIGHT_ERT;
   339|         StoreWord:     A_Right_SELD1 =`A_RIGHT_ERT;
   340|         StoreLong:     A_Right_SELD1 =`A_RIGHT_ERT;
   341|         `andi    :     A_Right_SELD1 =`Imm_unsigned ;   
   342|                  `addi     :       A_Right_SELD1 =`Imm_signed  ;
   343|         `addiu    :     A_Right_SELD1 =`Imm_signed;
   344|                  `ori      :         A_Right_SELD1 =`Imm_unsigned;
   345|         `xori    :     A_Right_SELD1 =`Imm_unsigned;
   346|
   347|         `beq        :   A_Right_SELD1 =`A_RIGHT_ERT;  
   348|         `bgtz       :   A_Right_SELD1 =`A_RIGHT_ERT;    
   349|                        `blez        :          A_Right_SELD1 =`A_RIGHT_ERT; 
   350|                        `bne         :          A_Right_SELD1 =`A_RIGHT_ERT;
   351|
   352|
   353|         `comp_im_signed   : A_Right_SELD1 =`Imm_signed;
   354|         `comp_im_unsigned : A_Right_SELD1 =`Imm_signed;
   355|
   356|         6'b00_000?:
   357|                case   (opfunc_ir)
   358|                 
   359|                 default           : A_Right_SELD1 =`A_RIGHT_ERT;
   360|                endcase
   361|         default: A_Right_SELD1 =`Imm_signed;
   362|          endcase
   363| end
   364|
   365|//フォワーディング回路
   366| assign rf_target_out= (rf_dest_addr_lr==IR[20:16] && rf_write_lr &&  A_Right_SELD1==`A_RIGHT_ERT) ? AReg_input :
   367|                    (rf_dest_addr_a==IR[20:16] && rf_write_a &&   A_Right_SELD1==`A_RIGHT_ERT) ? rf_input : qa;
   368|
   369| assign rf_source_out=(rf_dest_addr_lr==IR[25:21] && rf_write_lr  )  ? AReg_input :
   370|                   (rf_dest_addr_a==IR[25:21] && rf_write_a) ?  rf_input : qb;
   371|
   372|//ステージ2-------------------------------------------------------------------------------
   373|
   374|
   375|//IR_LR
   376| always @(posedge clock) begin
   377|        if (sync_reset) IR_LR<=NOP_INSTRUCTION;
   378|        else if (!dstall) IR_LR<=IR;
   379| end
   380|
   381|//RegWrite;
   382| always @ (posedge clock) begin
   383|  if (sync_reset) rf_write_lr<=0;
   384| else if (dstall);
   385| else 
   386|         case (opcode_ir)
   387|         LoadByteSigned    :       rf_write_lr <=1'b1;   
   388|                   LoadByteUnsigned :       rf_write_lr <=1'b1;
   389|                   LoadWordSigned    :       rf_write_lr <=1'b1;
   390|                   LoadWordUnsigned :      rf_write_lr <=1'b1;
   391|                   LoadLong        :            rf_write_lr <=1'b1;
   392|         `jump_and_link_im:        rf_write_lr <=1'b1;
   393|         COP0:  begin
   394|                        case (IR_LR[25:21])     
   395|                         MF:    rf_write_lr<=1'b1;
   396|                         default: rf_write_lr<=1'b0;
   397|                        endcase
   398|                 end
   399|                                        
   400|         6'b00_0000: 
   401|                case   (opfunc_ir)
   402|         //      `jump_and_link_register:  rf_write_lr <=1'b1;
   403|                         `divs:  rf_write_lr<=1'b0;
   404|                         `divu:  rf_write_lr<=1'b0;
   405|                         `muls: rf_write_lr<=1'b0;
   406|                         `mulu: rf_write_lr<=1'b0;
   407|                 default:                  rf_write_lr <=1'b1;
   408|                endcase
   409|         `andi            :        rf_write_lr    <=1'b1;        
   410|                   `addi             :     rf_write_lr   <=1'b1 ;
   411|         `addiu           :        rf_write_lr  <=1'b1;
   412|                    `ori              :     rf_write_lr  <=1'b1;
   413|         `xori     :       rf_write_lr  <=1'b1;
   414|         `lui      :              rf_write_lr <=1'b1;
   415|              `comp_im_signed    : rf_write_lr <=1'b1;
   416|              `comp_im_unsigned : rf_write_lr <=1'b1;
   417|         default:                  rf_write_lr <=1'b0;
   418|        endcase
   419| end
   420|
   421| 
   422|//Sreg
   423| always @(posedge clock) begin
   424|        if (sync_reset) Sreg<=0;
   425|        else if (!(dstall))  Sreg<=rf_source_out;
   426| end
   427|
   428|//Treg
   429| always @(posedge clock) begin
   430|        if (sync_reset) Treg<=0;
   431|        else if (!dstall)  begin
   432|         case (A_Right_SELD1)
   433|                `Imm_signed   :  Treg<={ {16{IR[15]}},IR[15:0]};
   434|                `Imm_unsigned :  Treg<={ 16'h000,IR[15:0]};
   435|                `A_RIGHT_ERT  :   Treg<=rf_target_out;
   436|               `IMM_26_SEL:       Treg<={6'b00_0000,IR[25:0]};
   437|                default         :       Treg<={ {16{IR[15]}},IR[15:0]};
   438|         endcase
   439|        end
   440| end
   441|
   442|//piplelined pc R31にセーブ用
   443|        always @(posedge clock) if (!dstall) pc_dd<=pc_d;
   444|
   445|//destination register
   446| reg [1:0] RF_input_addr_selD1;
   447| always @ (*) begin
   448|          case (opcode_ir)
   449|                `andi            : RF_input_addr_selD1=`RF_Ert_sel;      
   450|                         `addi            : RF_input_addr_selD1 =`RF_Ert_sel;
   451|                         `ori             : RF_input_addr_selD1 =`RF_Ert_sel;
   452|                `xori     : RF_input_addr_selD1=`RF_Ert_sel;
   453|                `jump_and_link_im: RF_input_addr_selD1=`RF_R15_SEL;
   454|                 `lui     : RF_input_addr_selD1 =`RF_Ert_sel;
   455|                `comp_im_signed  : RF_input_addr_selD1 =`RF_Ert_sel;
   456|                `comp_im_unsigned: RF_input_addr_selD1=`RF_Ert_sel;
   457|         6'b00_0000: 
   458|                case   (opfunc_ir)
   459|                 `jump_and_link_register: RF_input_addr_selD1=`RF_R15_SEL;
   460|                
   461|                 default          : RF_input_addr_selD1=`RF_Erd_sel;
   462|                endcase
   463|         default: RF_input_addr_selD1=`RF_Ert_sel;
   464|            endcase
   465| end
   466|
   467| always @ (posedge clock) begin
   468|        if(sync_reset) rf_dest_addr_lr<=0;
   469|        else if (dstall);
   470|        else
   471|         case (RF_input_addr_selD1)
   472|         `RF_Ert_sel: rf_dest_addr_lr <= IR[20:16];//ターゲットアドレス
   473|         `RF_Erd_sel: rf_dest_addr_lr <=IR[15:11];//デスティネーションアド列す
   474|         `RF_R15_SEL: rf_dest_addr_lr <=R31;//R31 
   475| //      `RF_INTR_SEL:rf_dest_addr_lr <=EPC <<1;//上位32ビットにマップ
   476|          default   :     rf_dest_addr_lr <= IR[20:16];
   477|         endcase
   478| end
   479|
   480|//ステージ3
   481|// 機能セレクタ(組み合わせ回路)
   482| reg [2:0] alu_out_sel;
   483| reg mul_div_result_read,copro_read;
   484| reg shift_reg_sel;
   485| reg [1:0] shift_func_sel;
   486| reg [3:0] alu_func_sel;
   487|
   488| wire [4:0] nshift;//シフト量
   489| wire [31:0] alu_out;
   490|
   491| //乗除算
   492| wire mul_div_sign;
   493| wire mul_div_div_select;
   494| wire [31:0] c_mult;
   495| wire mul_div_lohi_select;
   496|
   497| always @(posedge clock) begin
   498|        if (sync_reset) A_Right_Sel_lr<=`Imm_signed;
   499|        else if(!dstall)  A_Right_Sel_lr<=A_Right_SELD1;
   500| end
   501|
   502|//ALU インターフェース
   503| assign alu_source=Sreg;
   504| assign alu_target= Treg;
   505|
   506|alu  alu1(.a(alu_source),.b(alu_target),.alu_func(alu_func_sel),.alu_out(alu_out));
   507|
   508|//バレルシフタ インターフェース
   509|shifter sh1(.a(alu_target),.shift_out(shift_out),.shift_func(shift_func_sel),
   510|                        .shift_amount(nshift));
   511|
   512|//シフト量
   513|assign nshift=shift_reg_sel ? alu_source[4:0] : shifts;//レジスタによるシフトか即値による
   514|
   515|
   516|//乗除算モジュール
   517|mul_div MulDiv(.clock(clock),.sync_reset(sync_reset),.a(alu_source),.b(alu_target),
   518|           .mul_div_out(c_mult),.mul_div_sign(mul_div_sign),
   519|           .mul_div_mode(mul_div_div_select),
   520|           .mul_div_finished(mul_div_finished),.mul_div_start(mul_div_start),.lohi_select(mul_div_lohi_select),
   521|           .rf_input(Sreg),.high_write(mul_div_high_write),.low_write(mul_div_low_write));
   522|
   523|
   524|
   525|assign mul_div_div_select=IR_LR[1];//
   526|assign mul_div_sign=!IR_LR[0];
   527|assign mul_div_lohi_select=IR_LR[1];//MFHI 0 /MFLO 1
   528|
   529|//メモリインターフェース
   530|wire [31:0] w_mem_addr=alu_source+{ {16{IR_LR[15]}},IR_LR[15:0]};//32ビットに符号拡張
   531|wire [31:0] pre_mem_addr=rf_source_out+{ {16{IR[15]}},IR[15:0]};//キャッシュ付では、1CKアドレスを速く送出させないと
   532| //キャッシュヒットの判定(キャッシュにライトさせるかどうか)が間に合わない
   533|      //欲しいのはアドレスだけなのでアドレスだけ早く送出する
   534|wire [31:0] w_data_to_mem=alu_target;
   535|
   536|
   537|
   538|
   539| assign mem_addr= pre_mem_addr;
   540| 
   541|`ifdef BYTE_IN_CPU_CORE
   542| wire [7:0] dport0,dport1,dport2,dport3;
   543|
   544| assign dport0=w_data_to_mem[7:0] ;
   545| assign dport1=mem_access_mode !=`BYTE_ACCESS ? w_data_to_mem[15:8] :w_data_to_mem[7:0];
   546| assign dport2=mem_access_mode==`LONG_ACCESS ? w_data_to_mem[23:16] : w_data_to_mem[7:0];
   547| assign dport3=mem_access_mode==`LONG_ACCESS ? w_data_to_mem[31:24] : 
   548|              mem_access_mode==`WORD_ACCESS ? w_data_to_mem[15:8]  : w_data_to_mem[7:0];
   549|
   550| assign data_to_mem={dport3,dport2,dport1,dport0};      
   551|`else
   552| assign data_to_mem= w_data_to_mem;
   553|
   554|`endif
   555|      
   556| wire [5:0] opcode_ir_lr=IR_LR[31:26];
   557| wire [5:0] opfunc_ir_lr=IR_LR[5:0];
   558|
   559| always @ (*) begin
   560|         case (opcode_ir_lr)
   561|         6'b00_0000: 
   562|                case   (opfunc_ir_lr)
   563|                 `lsl            : shift_func_sel=`SHIFT_LEFT;
   564|                      `sllv         : shift_func_sel =`SHIFT_LEFT;
   565|                         `asr             : shift_func_sel=`SHIFT_RIGHT_SIGNED;
   566|                 `srav   : shift_func_sel=`SHIFT_RIGHT_SIGNED;
   567|                                `lsr             : shift_func_sel =`SHIFT_RIGHT_UNSIGNED;
   568|                 `srlv   : shift_func_sel=`SHIFT_RIGHT_UNSIGNED;
   569|                 default          : shift_func_sel=`SHIFT_LEFT;//Jul.5.2004 `SHIFT_NOTHING;
   570|                endcase
   571|         default: shift_func_sel=`SHIFT_LEFT;//Jul.5.2004`SHIFT_NOTHING;
   572|             endcase
   573| end
   574|
   575| always @ (*) begin
   576|           case (opcode_ir_lr)
   577|         `lui   :                begin
   578|                                alu_out_sel =`SHIFT16_SEL;
   579|                                shift_reg_sel=`SHIFT_AMOUNT_IMM_SEL;
   580|                                mul_div_result_read=0;
   581|                                copro_read=0;
   582|                          end
   583|         `jump_and_link_im:  
   584|                          begin
   585|                                alu_out_sel =`RF_PC_SEL;
   586|                                shift_reg_sel=`SHIFT_AMOUNT_IMM_SEL;
   587|                                mul_div_result_read=0;
   588|                                copro_read=0;
   589|                         end
   590|         COP0:  begin
   591|                        case (IR_LR[25:21])     
   592|                         MF:
   593|                                 begin
   594|                                         alu_out_sel=RF_PC_SEL;
   595|                                         shift_reg_sel=`SHIFT_AMOUNT_IMM_SEL;
   596|                                        mul_div_result_read=0;
   597|                                         copro_read=1;
   598|                                 end
   599|                         default:       
   600|                                 begin
   601|                                         alu_out_sel=RF_ALU_sel;
   602|                                         shift_reg_sel=`SHIFT_AMOUNT_IMM_SEL;
   603|                                        mul_div_result_read=0;
   604|                                        copro_read=0;
   605|                                 end
   606|                        endcase
   607|                 end
   608|               SPECIAL:
   609|                case   (opfunc_ir_lr)
   610|                     `jump_and_link_register :
   611|                                 begin 
   612|                                        alu_out_sel=RF_PC_SEL;
   613|                                        shift_reg_sel=`SHIFT_AMOUNT_IMM_SEL;
   614|                                        mul_div_result_read=0;
   615|                                        copro_read=0;
   616|                                 end
   617|                    `lsl ,  `asr   ,  `lsr         :    begin
   618|                                         alu_out_sel=RF_Shifter_sel ;
   619|                                         shift_reg_sel=`SHIFT_AMOUNT_IMM_SEL;
   620|                                        mul_div_result_read=0;
   621|                                        copro_read=0;
   622|                                        end 
   623|                 `sllv, `srav    ,      `srlv           :      begin
   624|                                          alu_out_sel=RF_Shifter_sel ;
   625|                                          shift_reg_sel=`SHIFT_AMOUNT_REG_SEL;
   626|                                        mul_div_result_read=0;
   627|                                        copro_read=0;
   628|                                  end    
   629|                                
   630|                             
   631|
   632|
   633|                 `mfhi , `mflo   :      begin
   634|                                                alu_out_sel=RF_PC_SEL;
   635|                                                 shift_reg_sel=`SHIFT_AMOUNT_IMM_SEL;
   636|                                                mul_div_result_read=1;
   637|                                                copro_read=0;
   638|                                         end
   639|                 default              :      begin
   640|                                        alu_out_sel=RF_ALU_sel;
   641|                                         shift_reg_sel=`SHIFT_AMOUNT_IMM_SEL;
   642|                                        mul_div_result_read=0;
   643|                                        copro_read=0;
   644|                                 end
   645|                endcase
   646|         default: begin
   647|                         alu_out_sel=RF_ALU_sel;
   648|                         shift_reg_sel=`SHIFT_AMOUNT_IMM_SEL;
   649|                        mul_div_result_read=0;
   650|                        copro_read=0;
   651|                 end
   652|             endcase
   653| end
   654|
   655| always @ (*) begin
   656|        case (opcode_ir_lr)
   657|                `andi    : alu_func_sel =`ALU_AND;
   658|                 `addi    : alu_func_sel =`ALU_ADD  ;
   659|                `addiu  :  alu_func_sel =`ALU_ADD;
   660|                `ori     : alu_func_sel =`ALU_OR;
   661|                 `xori    : alu_func_sel =`ALU_XOR;
   662|                 `comp_im_signed     : alu_func_sel =`ALU_LESS_THAN_SIGNED;
   663|                         `comp_im_unsigned   : alu_func_sel =`ALU_LESS_THAN_UNSIGNED;
   664|                6'b00_0000: 
   665|                case   (opfunc_ir_lr)
   666|                 `add    : alu_func_sel =`ALU_ADD ;
   667|                 `addu   :       alu_func_sel=`ALU_ADD ;        
   668|                                `sub     : alu_func_sel=`ALU_SUBTRACT;
   669|                 `subu   : alu_func_sel=`ALU_SUBTRACT;
   670|                 `and     : alu_func_sel=`ALU_AND;
   671|                 `nor     : alu_func_sel=`ALU_NOR;
   672|                 `or      : alu_func_sel=`ALU_OR;
   673|                 `xor     : alu_func_sel=`ALU_XOR;
   674|                               `comp_signed      : alu_func_sel=`ALU_LESS_THAN_SIGNED;   
   675|                              `comp_unsigned     : alu_func_sel=`ALU_LESS_THAN_UNSIGNED; 
   676|                            
   677|                 default           : alu_func_sel=`ALU_NOTHING;//Jul.6.2004 ALU_NOTHING;
   678|                endcase
   679|               default: alu_func_sel=`ALU_NOTHING;//Jul.6.2004 ALU_NOTHING;
   680|        endcase
   681| end
   682|
   683|//M_sign
   684| reg M_sign;
   685| always @ (*) begin
   686|        case (opcode_ir_lr)
   687|              LoadByteSigned  :     M_sign=`M_signed;    
   688|                        LoadByteUnsigned :   M_sign=`M_unsigned;
   689|                        LoadWordSigned  :     M_sign=`M_signed;
   690|                        LoadWordUnsigned :  M_sign=`M_unsigned;
   691|                        LoadLong           :       M_sign=`M_unsigned;
   692|              StoreByte:             M_sign=`M_unsigned; 
   693|              StoreWord:             M_sign=`M_unsigned;
   694|                        StoreLong:           M_sign=`M_unsigned;
   695|                default:                  M_sign=`M_unsigned;
   696|             endcase
   697| end
   698|
   699|
   700|
   701|
   702|// [1:0] M_access_mode
   703| reg [1:0] M_access_mode;
   704| always @ (*) begin
   705|         case (opcode_ir_lr)
   706|         LoadByteSigned  :        M_access_mode=`BYTE_ACCESS;    
   707|                   LoadByteUnsigned :     M_access_mode=`BYTE_ACCESS;
   708|                   LoadWordSigned  :       M_access_mode=`WORD_ACCESS;
   709|                   LoadWordUnsigned :    M_access_mode=`WORD_ACCESS;
   710|                   LoadLong        :          M_access_mode=`LONG_ACCESS;
   711|              StoreByte:                M_access_mode=`BYTE_ACCESS;     
   712|         StoreWord:             M_access_mode=`WORD_ACCESS;
   713|                   StoreLong:           M_access_mode=`LONG_ACCESS;
   714|         default:                     M_access_mode=`LONG_ACCESS;
   715|          endcase
   716| end
   717|//prefetch address 用
   718| 
   719| always @ (*) begin
   720|         case (opcode_ir)
   721|         LoadByteSigned  :        begin pre_rw_access=1; pre_read_access=1; end  
   722|                   LoadByteUnsigned :      begin pre_rw_access=1;pre_read_access=1; end 
   723|                   LoadWordSigned  :        begin pre_rw_access=1;pre_read_access=1;    end
   724|                   LoadWordUnsigned :     begin pre_rw_access=1;pre_read_access=1;      end
   725|                   LoadLong        :           begin pre_rw_access=1;pre_read_access=1; end
   726|              StoreByte:                 begin pre_rw_access=1;pre_read_access=0;       end     
   727|         StoreWord:              begin pre_rw_access=1;pre_read_access=0;       end
   728|                   StoreLong:            begin pre_rw_access=1;pre_read_access=0;       end
   729|         default:                      begin pre_rw_access=0;pre_read_access=0; end
   730|          endcase
   731| end
   732|
   733|//MWrite
   734| reg mem_write;
   735|//      always @ (*) begin
   736|//       case (opcode_ir_lr)
   737|//              StoreByte:      mem_write=1'b1; 
   738|//              StoreWord:      mem_write=1'b1;
   739|   //                   StoreLong:      mem_write=1'b1;
   740|//              default:        mem_write=1'b0;
   741|//        endcase
   742|   //  end
   743| 
   744| always @ (*) begin
   745|        case (opcode_ir_lr)
   746|         StoreByte:     mem_write=1'b1; 
   747|         StoreWord:     mem_write=1'b1;
   748|                        StoreLong:      mem_write=1'b1;
   749|         default:        mem_write=1'b0;
   750|         endcase
   751|     end
   752| assign mem_write_req= mem_write;
   753| 
   754| assign mem_access_mode= M_access_mode;
   755| assign mem_sign= M_sign;
   756|
   757|
   758|
   759|//IR_A
   760| always @(posedge clock) begin
   761|        if (sync_reset) IR_A<=NOP_INSTRUCTION;
   762|        else if (!dstall) IR_A<=IR_LR;
   763| end
   764|//rf_write_a
   765|
   766| always @ (posedge clock) begin
   767|        if (sync_reset) rf_write_a<=0;
   768|        else if (!dstall) rf_write_a<=rf_write_lr;
   769|        end
   770|//AReg
   771| 
   772| assign AReg_input=dstall ? AReg :alu_out_sel==RF_ALU_sel ?     alu_out :
   773|                                  alu_out_sel==RF_Shifter_sel ? shift_out :
   774|                                 alu_out_sel==SHIFT16_SEL ?  {IR_LR[15:0],16'h00} : 
   775|                                 mul_div_result_read ? c_mult :
   776|                                 copro_read ? copro_output :
   777|                                 pc_dd; 
   778| always @(posedge clock) begin
   779|        if (sync_reset) AReg<=0;
   780|        else  AReg<=AReg_input;
   781| 
   782| end
   783|
   784| 
   785| always @(posedge clock) begin
   786|        if (!dstall) rf_dest_addr_a<=rf_dest_addr_lr;
   787|
   788|
   789| end
   790|
   791|//ステージ4
   792| wire [5:0] opcode_ir_a=IR_A[31:26];
   793| wire [5:0] opfunc_ir_a=IR_A[5:0];
   794| wire target_sel;
   795| wire r31_sel;
   796|
   797|//      wire mem_read_req= opcode_ir_a==LoadByteSigned  ||
   798|//                 opcode_ir_a==LoadByteUnsigned ||
   799|//                 opcode_ir_a==LoadWordSigned ||
   800|//                 opcode_ir_a==LoadWordUnsigned ||
   801|//                 opcode_ir_a==LoadLong ;
   802| 
   803|
   804|//       
   805| assign mem_read_req= opcode_ir_a==LoadByteSigned  ||
   806|                  opcode_ir_a==LoadByteUnsigned ||
   807|                  opcode_ir_a==LoadWordSigned ||
   808|                  opcode_ir_a==LoadWordUnsigned ||
   809|                  opcode_ir_a==LoadLong ;
   810|
   811|
   812|
   813|//`define DEBUG
   814|`ifdef DEBUG
   815| integer fi;
   816|  `ifdef REFERENCE_SIM
   817|         initial fi=$fopen("pc_file_ref.txt","w");
   818| `else
   819|        initial fi=$fopen("pc_file.txt","w");
   820| `endif
   821|
   822|
   823| initial debug1.counter=0;
   824| reg [31:0] load_address_ir,load_address_ir_lr,load_address_ir_a; 
   825| 
   826| always @(posedge clock) begin:debug1
   827|        integer counter;
   828|        integer i;
   829|
   830|        if (~dstall & pre_rw_access) load_address_ir_lr<=pre_mem_addr;
   831|        if(!dstall) load_address_ir_a<=load_address_ir_lr;
   832|        
   833|
   834| 
   835|        if (!dstall ) begin 
   836|         $fdisplay(fi,"%6d PC=%8h IR=%8h ",counter,PC,IR);
   837|         counter<=counter+1;
   838|         `ifdef REG_DEBUG_OUT
   839|                for (i=0;i<=31;i=i+1) begin
   840|                 $fwrite(fi,"R[%02h]=%h ",i,ram_regfile32xx32.mem[i]);
   841|                end
   842|                $fdisplay(fi,"");
   843|         `endif
   844|        end
   845|        if (mem_write_req && !dstall) begin
   846|         if (opcode_ir_lr==StoreByte    )       $fdisplay(fi,"Store_Byte         addr=%8h data=%2h",load_address_ir_lr,data_to_mem[7:0]);
   847|         else if (opcode_ir_lr==StoreWord        )      $fdisplay(fi,"Store_Word         addr=%8h data=%4h",load_address_ir_lr,data_to_mem[15:0]);
   848|         else  $fdisplay(fi,"Store_Long         addr=%8h data=%8h",load_address_ir_lr,data_to_mem[31:0]);
   849|         
   850|        end
   851|        if (mem_read_req && !dstall) begin
   852|         if (opcode_ir_a==LoadByteSigned ||
   853|             opcode_ir_a==LoadByteUnsigned      )       $fdisplay(fi,"Load_Byte         addr=%8h  data=%2h",load_address_ir_a,data_fm_mem[7:0]);
   854|         else if (opcode_ir_a==LoadWordSigned ||
   855|                    opcode_ir_a==LoadWordUnsigned
   856|                )       $fdisplay(fi,"Load_Word         addr=%8h  data=%4h",load_address_ir_a,data_fm_mem[15:0]);
   857|         else  $fdisplay(fi,"Load_Long    addr=%8h data=%8h",load_address_ir_a,data_fm_mem[31:0]);
   858|         
   859|        end
   860|
   861| end
   862|
   863|`include "disasm.v"
   864|`endif
   865| wire [31:0] areg_or_mem_out=mem_read_req ? data_fm_mem : AReg;
   866| assign rf_input= areg_or_mem_out;
   867|
   868| 
   869| assign rf_write_addr=rf_dest_addr_a;
   870|
   871|
   872|
   873|
   874|endmodule
   875|         
   876| 
   877|