`define OR1200_DCFGR_NDP 3'h0 // Zero DVR/DCR pairs `define OR1200_DCFGR_WPCI 1'b0 // WP counters not impl. `define OR1200_DCFGR_RES1 28'h0000000 `define OR1200_M2R_BYTE0 4'b0000 `define OR1200_M2R_BYTE1 4'b0001 `define OR1200_M2R_BYTE2 4'b0010 `define OR1200_M2R_BYTE3 4'b0011 `define OR1200_M2R_EXTB0 4'b0100 `define OR1200_M2R_EXTB1 4'b0101 `define OR1200_M2R_EXTB2 4'b0110 `define OR1200_M2R_EXTB3 4'b0111 `define OR1200_M2R_ZERO 4'b0000 `define OR1200_ICCFGR_NCW 3'h0 // 1 cache way `define OR1200_ICCFGR_NCS 9 // Num cache sets `define OR1200_ICCFGR_CBS 9 // 16 byte cache block `define OR1200_ICCFGR_CWS 1'b0 // Irrelevant `define OR1200_ICCFGR_CCRI 1'b1 // Cache control reg impl. `define OR1200_ICCFGR_CBIRI 1'b1 // Cache block inv reg impl. `define OR1200_ICCFGR_CBPRI 1'b0 // Cache block prefetch reg not impl. `define OR1200_ICCFGR_CBLRI 1'b0 // Cache block lock reg not impl. `define OR1200_ICCFGR_CBFRI 1'b1 // Cache block flush reg impl. `define OR1200_ICCFGR_CBWBRI 1'b0 // Irrelevant `define OR1200_ICCFGR_RES1 17'h00000 //`define OR1200_ICCFGR_NCW_BITS 2:0 //`define OR1200_ICCFGR_NCS_BITS 6:3 `define OR1200_ICCFGR_CBS_BITS 7 `define OR1200_ICCFGR_CWS_BITS 8 `define OR1200_ICCFGR_CCRI_BITS 9 `define OR1200_ICCFGR_CBIRI_BITS 10 `define OR1200_ICCFGR_CBPRI_BITS 11 `define OR1200_ICCFGR_CBLRI_BITS 12 `define OR1200_ICCFGR_CBFRI_BITS 13 `define OR1200_ICCFGR_CBWBRI_BITS 14 //`define OR1200_ICCFGR_RES1_BITS 31:15 `define OR1200_DCCFGR_NCW 3'h0 // 1 cache way `define OR1200_DCCFGR_NCS 9 // Num cache sets `define OR1200_DCCFGR_CBS 9 // 16 byte cache block `define OR1200_DCCFGR_CWS 1'b0 // Write-through strategy `define OR1200_DCCFGR_CCRI 1'b1 // Cache control reg impl. `define OR1200_DCCFGR_CBIRI 1'b1 // Cache block inv reg impl. `define OR1200_DCCFGR_CBPRI 1'b0 // Cache block prefetch reg not impl. `define OR1200_DCCFGR_CBLRI 1'b0 // Cache block lock reg not impl. `define OR1200_DCCFGR_CBFRI 1'b1 // Cache block flush reg impl. `define OR1200_DCCFGR_CBWBRI 1'b0 // Cache block WB reg not impl. `define OR1200_DCCFGR_RES1 17'h00000 //`define OR1200_DCCFGR_NCW_BITS 2:0 //`define OR1200_DCCFGR_NCS_BITS 6:3 `define OR1200_DCCFGR_CBS_BITS 7 `define OR1200_DCCFGR_CWS_BITS 8 `define OR1200_DCCFGR_CCRI_BITS 9 `define OR1200_DCCFGR_CBIRI_BITS 10 `define OR1200_DCCFGR_CBPRI_BITS 11 `define OR1200_DCCFGR_CBLRI_BITS 12 `define OR1200_DCCFGR_CBFRI_BITS 13 `define OR1200_DCCFGR_CBWBRI_BITS 14 //`define OR1200_DCCFGR_RES1_BITS 31:15 `define OR1200_IMMUCFGR_NTW 2'h0 // 1 TLB way `define OR1200_IMMUCFGR_NTS 3'b101 // Num TLB sets `define OR1200_IMMUCFGR_NAE 3'h0 // No ATB entry `define OR1200_IMMUCFGR_CRI 1'b0 // No control reg `define OR1200_IMMUCFGR_PRI 1'b0 // No protection reg `define OR1200_IMMUCFGR_TEIRI 1'b1 // TLB entry inv reg impl `define OR1200_IMMUCFGR_HTR 1'b0 // No HW TLB reload `define OR1200_IMMUCFGR_RES1 20'h00000 // CPUCFGR fields //`define OR1200_CPUCFGR_NSGF_BITS 3:0 `define OR1200_CPUCFGR_HGF_BITS 4 `define OR1200_CPUCFGR_OB32S_BITS 5 `define OR1200_CPUCFGR_OB64S_BITS 6 `define OR1200_CPUCFGR_OF32S_BITS 7 `define OR1200_CPUCFGR_OF64S_BITS 8 `define OR1200_CPUCFGR_OV64S_BITS 9 //`define OR1200_CPUCFGR_RES1_BITS 31:10 // CPUCFGR values `define OR1200_CPUCFGR_NSGF 4'h0 `define OR1200_CPUCFGR_HGF 1'b0 `define OR1200_CPUCFGR_OB32S 1'b1 `define OR1200_CPUCFGR_OB64S 1'b0 `define OR1200_CPUCFGR_OF32S 1'b0 `define OR1200_CPUCFGR_OF64S 1'b0 `define OR1200_CPUCFGR_OV64S 1'b0 `define OR1200_CPUCFGR_RES1 22'h000000 // DMMUCFGR fields /* `define OR1200_DMMUCFGR_NTW_BITS 1:0 `define OR1200_DMMUCFGR_NTS_BITS 4:2 `define OR1200_DMMUCFGR_NAE_BITS 7:5 */ `define OR1200_DMMUCFGR_CRI_BITS 8 `define OR1200_DMMUCFGR_PRI_BITS 9 `define OR1200_DMMUCFGR_TEIRI_BITS 10 `define OR1200_DMMUCFGR_HTR_BITS 11 //`define OR1200_DMMUCFGR_RES1_BITS 31:12 // DMMUCFGR values `define OR1200_DMMUCFGR_NTW 2'h0 // 1 TLB way `define OR1200_DMMUCFGR_NTS 3'b110 // Num TLB sets `define OR1200_DMMUCFGR_NAE 3'h0 // No ATB entries `define OR1200_DMMUCFGR_CRI 1'b0 // No control register `define OR1200_DMMUCFGR_PRI 1'b0 // No protection reg `define OR1200_DMMUCFGR_TEIRI 1'b1 // TLB entry inv reg impl. `define OR1200_DMMUCFGR_HTR 1'b0 // No HW TLB reload `define OR1200_DMMUCFGR_RES1 20'h00000 // IMMUCFGR fields /* `define OR1200_IMMUCFGR_NTW_BITS 1:0 `define OR1200_IMMUCFGR_NTS_BITS 4:2 `define OR1200_IMMUCFGR_NAE_BITS 7:5 */ `define OR1200_IMMUCFGR_CRI_BITS 8 `define OR1200_IMMUCFGR_PRI_BITS 9 `define OR1200_IMMUCFGR_TEIRI_BITS 10 `define OR1200_IMMUCFGR_HTR_BITS 11 //`define OR1200_IMMUCFGR_RES1_BITS 31:12 `define OR1200_SPRGRP_SYS_VR 4'h0 `define OR1200_SPRGRP_SYS_UPR 4'h1 `define OR1200_SPRGRP_SYS_CPUCFGR 4'h2 `define OR1200_SPRGRP_SYS_DMMUCFGR 4'h3 `define OR1200_SPRGRP_SYS_IMMUCFGR 4'h4 `define OR1200_SPRGRP_SYS_DCCFGR 4'h5 `define OR1200_SPRGRP_SYS_ICCFGR 4'h6 `define OR1200_SPRGRP_SYS_DCFGR 4'h7 // VR fields /* `define OR1200_VR_REV_BITS 5:0 `define OR1200_VR_RES1_BITS 15:6 `define OR1200_VR_CFG_BITS 23:16 `define OR1200_VR_VER_BITS 31:24 */ // VR values `define OR1200_VR_REV 6'h01 `define OR1200_VR_RES1 10'h000 `define OR1200_VR_CFG 8'h00 `define OR1200_VR_VER 8'h12 `define OR1200_UPR_UP_BITS 0 `define OR1200_UPR_DCP_BITS 1 `define OR1200_UPR_ICP_BITS 2 `define OR1200_UPR_DMP_BITS 3 `define OR1200_UPR_IMP_BITS 4 `define OR1200_UPR_MP_BITS 5 `define OR1200_UPR_DUP_BITS 6 `define OR1200_UPR_PCUP_BITS 7 `define OR1200_UPR_PMP_BITS 8 `define OR1200_UPR_PICP_BITS 9 `define OR1200_UPR_TTP_BITS 10 /* `define OR1200_UPR_RES1_BITS 23:11 `define OR1200_UPR_CUP_BITS 31:24 */ `define OR1200_UPR_RES1 13'h0000 `define OR1200_UPR_CUP 8'h00 `define OR1200_DU_DSR_WIDTH 14 `define OR1200_EXCEPT_UNUSED 3'hf `define OR1200_EXCEPT_TRAP 3'he `define OR1200_EXCEPT_BREAK 3'hd `define OR1200_EXCEPT_SYSCALL 3'hc `define OR1200_EXCEPT_RANGE 3'hb `define OR1200_EXCEPT_ITLBMISS 3'ha `define OR1200_EXCEPT_DTLBMISS 3'h9 `define OR1200_EXCEPT_INT 3'h8 `define OR1200_EXCEPT_ILLEGAL 3'h7 `define OR1200_EXCEPT_ALIGN 3'h6 `define OR1200_EXCEPT_TICK 3'h5 `define OR1200_EXCEPT_IPF 3'h4 `define OR1200_EXCEPT_DPF 3'h3 `define OR1200_EXCEPT_BUSERR 3'h2 `define OR1200_EXCEPT_RESET 3'h1 `define OR1200_EXCEPT_NONE 3'h0 `define OR1200_OPERAND_WIDTH 32 `define OR1200_REGFILE_ADDR_WIDTH 5 `define OR1200_ALUOP_WIDTH 4 `define OR1200_ALUOP_NOP 4'b000 `define OR1200_ALUOP_ADD 4'b0000 `define OR1200_ALUOP_ADDC 4'b0001 `define OR1200_ALUOP_SUB 4'b0010 `define OR1200_ALUOP_AND 4'b0011 `define OR1200_ALUOP_OR 4'b0100 `define OR1200_ALUOP_XOR 4'b0101 `define OR1200_ALUOP_MUL 4'b0110 `define OR1200_ALUOP_CUST5 4'b0111 `define OR1200_ALUOP_SHROT 4'b1000 `define OR1200_ALUOP_DIV 4'b1001 `define OR1200_ALUOP_DIVU 4'b1010 `define OR1200_ALUOP_IMM 4'b1011 `define OR1200_ALUOP_MOVHI 4'b1100 `define OR1200_ALUOP_COMP 4'b1101 `define OR1200_ALUOP_MTSR 4'b1110 `define OR1200_ALUOP_MFSR 4'b1111 `define OR1200_ALUOP_CMOV 4'b1110 `define OR1200_ALUOP_FF1 4'b1111 `define OR1200_MACOP_WIDTH 2 `define OR1200_MACOP_NOP 2'b00 `define OR1200_MACOP_MAC 2'b01 `define OR1200_MACOP_MSB 2'b10 `define OR1200_SHROTOP_WIDTH 2 `define OR1200_SHROTOP_NOP 2'b00 `define OR1200_SHROTOP_SLL 2'b00 `define OR1200_SHROTOP_SRL 2'b01 `define OR1200_SHROTOP_SRA 2'b10 `define OR1200_SHROTOP_ROR 2'b11 // Execution cycles per instruction `define OR1200_MULTICYCLE_WIDTH 2 `define OR1200_ONE_CYCLE 2'b00 `define OR1200_TWO_CYCLES 2'b01 // Operand MUX selects `define OR1200_SEL_WIDTH 2 `define OR1200_SEL_RF 2'b00 `define OR1200_SEL_IMM 2'b01 `define OR1200_SEL_EX_FORW 2'b10 `define OR1200_SEL_WB_FORW 2'b11 // // BRANCHOPs // `define OR1200_BRANCHOP_WIDTH 3 `define OR1200_BRANCHOP_NOP 3'b000 `define OR1200_BRANCHOP_J 3'b001 `define OR1200_BRANCHOP_JR 3'b010 `define OR1200_BRANCHOP_BAL 3'b011 `define OR1200_BRANCHOP_BF 3'b100 `define OR1200_BRANCHOP_BNF 3'b101 `define OR1200_BRANCHOP_RFE 3'b110 // // LSUOPs // // Bit 0: sign extend // Bits 1-2: 00 doubleword, 01 byte, 10 halfword, 11 singleword // Bit 3: 0 load, 1 store `define OR1200_LSUOP_WIDTH 4 `define OR1200_LSUOP_NOP 4'b0000 `define OR1200_LSUOP_LBZ 4'b0010 `define OR1200_LSUOP_LBS 4'b0011 `define OR1200_LSUOP_LHZ 4'b0100 `define OR1200_LSUOP_LHS 4'b0101 `define OR1200_LSUOP_LWZ 4'b0110 `define OR1200_LSUOP_LWS 4'b0111 `define OR1200_LSUOP_LD 4'b0001 `define OR1200_LSUOP_SD 4'b1000 `define OR1200_LSUOP_SB 4'b1010 `define OR1200_LSUOP_SH 4'b1100 `define OR1200_LSUOP_SW 4'b1110 // FETCHOPs `define OR1200_FETCHOP_WIDTH 1 `define OR1200_FETCHOP_NOP 1'b0 `define OR1200_FETCHOP_LW 1'b1 // // Register File Write-Back OPs // // Bit 0: register file write enable // Bits 2-1: write-back mux selects `define OR1200_RFWBOP_WIDTH 3 `define OR1200_RFWBOP_NOP 3'b000 `define OR1200_RFWBOP_ALU 3'b001 `define OR1200_RFWBOP_LSU 3'b011 `define OR1200_RFWBOP_SPRS 3'b101 `define OR1200_RFWBOP_LR 3'b111 // Compare instructions `define OR1200_COP_SFEQ 3'b000 `define OR1200_COP_SFNE 3'b001 `define OR1200_COP_SFGT 3'b010 `define OR1200_COP_SFGE 3'b011 `define OR1200_COP_SFLT 3'b100 `define OR1200_COP_SFLE 3'b101 `define OR1200_COP_X 3'b111 `define OR1200_SIGNED_COMPARE 3'b011 `define OR1200_COMPOP_WIDTH 4 // // TAGs for instruction bus // `define OR1200_ITAG_IDLE 4'h0 // idle bus `define OR1200_ITAG_NI 4'h1 // normal insn `define OR1200_ITAG_BE 4'hb // Bus error exception `define OR1200_ITAG_PE 4'hc // Page fault exception `define OR1200_ITAG_TE 4'hd // TLB miss exception // // TAGs for data bus // `define OR1200_DTAG_IDLE 4'h0 // idle bus `define OR1200_DTAG_ND 4'h1 // normal data `define OR1200_DTAG_AE 4'ha // Alignment exception `define OR1200_DTAG_BE 4'hb // Bus error exception `define OR1200_DTAG_PE 4'hc // Page fault exception `define OR1200_DTAG_TE 4'hd // TLB miss exception `define OR1200_DU_DSR_RSTE 0 `define OR1200_DU_DSR_BUSEE 1 `define OR1200_DU_DSR_DPFE 2 `define OR1200_DU_DSR_IPFE 3 `define OR1200_DU_DSR_TTE 4 `define OR1200_DU_DSR_AE 5 `define OR1200_DU_DSR_IIE 6 `define OR1200_DU_DSR_IE 7 `define OR1200_DU_DSR_DME 8 `define OR1200_DU_DSR_IME 9 `define OR1200_DU_DSR_RE 10 `define OR1200_DU_DSR_SCE 11 `define OR1200_DU_DSR_BE 12 `define OR1200_DU_DSR_TE 13 ////////////////////////////////////////////// // // ORBIS32 ISA specifics // // SHROT_OP position in machine word //`define OR1200_SHROTOP_POS 7:6 // ALU instructions multicycle field in machine word //`define OR1200_ALUMCYC_POS 9:8 // // Instruction opcode groups (basic) // `define OR1200_OR32_J 6'b000000 `define OR1200_OR32_JAL 6'b000001 `define OR1200_OR32_BNF 6'b000011 `define OR1200_OR32_BF 6'b000100 `define OR1200_OR32_NOP 6'b000101 `define OR1200_OR32_MOVHI 6'b000110 `define OR1200_OR32_XSYNC 6'b001000 `define OR1200_OR32_RFE 6'b001001 /* */ `define OR1200_OR32_JR 6'b010001 `define OR1200_OR32_JALR 6'b010010 `define OR1200_OR32_MACI 6'b010011 /* */ `define OR1200_OR32_LWZ 6'b100001 `define OR1200_OR32_LBZ 6'b100011 `define OR1200_OR32_LBS 6'b100100 `define OR1200_OR32_LHZ 6'b100101 `define OR1200_OR32_LHS 6'b100110 `define OR1200_OR32_ADDI 6'b100111 `define OR1200_OR32_ADDIC 6'b101000 `define OR1200_OR32_ANDI 6'b101001 `define OR1200_OR32_ORI 6'b101010 `define OR1200_OR32_XORI 6'b101011 `define OR1200_OR32_MULI 6'b101100 `define OR1200_OR32_MFSPR 6'b101101 `define OR1200_OR32_SH_ROTI 6'b101110 `define OR1200_OR32_SFXXI 6'b101111 /* */ `define OR1200_OR32_MTSPR 6'b110000 `define OR1200_OR32_MACMSB 6'b110001 /* */ `define OR1200_OR32_SW 6'b110101 `define OR1200_OR32_SB 6'b110110 `define OR1200_OR32_SH 6'b110111 `define OR1200_OR32_ALU 6'b111000 `define OR1200_OR32_SFXX 6'b111001 `define OR1200_OR32_CUST5 6'b111100 ///////////////////////////////////////////////////// // // Exceptions // // // Exception vectors per OR1K architecture: // 0xPPPPP100 - reset // 0xPPPPP200 - bus error // ... etc // where P represents exception prefix. // // Exception vectors can be customized as per // the following formula: // 0xPPPPPNVV - exception N // // P represents exception prefix // N represents exception N // VV represents length of the individual vector space, // usually it is 8 bits wide and starts with all bits zero // // // PPPPP and VV parts // // Sum of these two defines needs to be 28 // `define OR1200_EXCEPT_EPH0_P 20'h00000 `define OR1200_EXCEPT_EPH1_P 20'hF0000 `define OR1200_EXCEPT_V 8'h00 // // N part width // `define OR1200_EXCEPT_WIDTH 4 `define OR1200_SPR_GROUP_SYS 5'b00000 `define OR1200_SPR_GROUP_DMMU 5'b00001 `define OR1200_SPR_GROUP_IMMU 5'b00010 `define OR1200_SPR_GROUP_DC 5'b00011 `define OR1200_SPR_GROUP_IC 5'b00100 `define OR1200_SPR_GROUP_MAC 5'b00101 `define OR1200_SPR_GROUP_DU 5'b00110 `define OR1200_SPR_GROUP_PM 5'b01000 `define OR1200_SPR_GROUP_PIC 5'b01001 `define OR1200_SPR_GROUP_TT 5'b01010 ///////////////////////////////////////////////////// // // System group // // // System registers // `define OR1200_SPR_CFGR 7'b0000000 `define OR1200_SPR_RF 6'b100000 // 1024 >> 5 `define OR1200_SPR_NPC 11'b00000010000 `define OR1200_SPR_SR 11'b00000010001 `define OR1200_SPR_PPC 11'b00000010010 `define OR1200_SPR_EPCR 11'b00000100000 `define OR1200_SPR_EEAR 11'b00000110000 `define OR1200_SPR_ESR 11'b00001000000 // // SR bits // `define OR1200_SR_WIDTH 16 `define OR1200_SR_SM 0 `define OR1200_SR_TEE 1 `define OR1200_SR_IEE 2 `define OR1200_SR_DCE 3 `define OR1200_SR_ICE 4 `define OR1200_SR_DME 5 `define OR1200_SR_IME 6 `define OR1200_SR_LEE 7 `define OR1200_SR_CE 8 `define OR1200_SR_F 9 `define OR1200_SR_CY 10 // Unused `define OR1200_SR_OV 11 // Unused `define OR1200_SR_OVE 12 // Unused `define OR1200_SR_DSX 13 // Unused `define OR1200_SR_EPH 14 `define OR1200_SR_FO 15 // // Bits that define offset inside the group // // Default Exception Prefix // // 1'b0 - OR1200_EXCEPT_EPH0_P (0x0000_0000) // 1'b1 - OR1200_EXCEPT_EPH1_P (0xF000_0000) // `define OR1200_SR_EPH_DEF 1'b0 ///////////////////////////////////////////////////// // // Power Management (PM) // // Bit positions inside PMR (don't change) `define OR1200_PM_PMR_DME 4 `define OR1200_PM_PMR_SME 5 `define OR1200_PM_PMR_DCGE 6 // PMR offset inside PM group of registers `define OR1200_PM_OFS_PMR 11'b0 // PM group `define OR1200_SPRGRP_PM 5'b01000 // Define it if you want PIC implemented // Define number of interrupt inputs (2-31) `define OR1200_PIC_INTS 20 // Address offsets of PIC registers inside PIC group `define OR1200_PIC_OFS_PICMR 2'b00 `define OR1200_PIC_OFS_PICSR 2'b10 // Position of offset bits inside SPR address // Address offsets of TT registers inside TT group `define OR1200_TT_OFS_TTMR 1'b0 `define OR1200_TT_OFS_TTCR 1'b1 // Position of offset bits inside SPR group `define OR1200_TTOFS_BITS 0 // TTMR bits `define OR1200_TT_TTMR_IP 28 `define OR1200_TT_TTMR_IE 29 ////////////////////////////////////////////// // // MAC // `define OR1200_MAC_ADDR 0 // MACLO 0xxxxxxxx1, MACHI 0xxxxxxxx0 // // Shift {MACHI,MACLO} into destination register when executing l.macrc // // According to architecture manual there is no shift, so default value is 0. // // However the implementation has deviated in this from the arch manual and had hard coded shift by 28 bits which // is a useful optimization for MP3 decoding (if using libmad fixed point library). Shifts are no longer // default setup, but if you need to remain backward compatible, define your shift bits, which were normally // dest_GPR = {MACHI,MACLO}[59:28] `define OR1200_MAC_SHIFTBY 0 // 0 = According to arch manual, 28 = obsolete backward compatibility ////////////////////////////////////////////// // // Data MMU (DMMU) // // // Address that selects between TLB TR and MR // `define OR1200_DTLB_TM_ADDR 7 // // DTLBMR fields // `define OR1200_DTLBMR_V_BITS 0 // DTLBTR fields // `define OR1200_DTLBTR_CC_BITS 0 `define OR1200_DTLBTR_CI_BITS 1 `define OR1200_DTLBTR_WBC_BITS 2 `define OR1200_DTLBTR_WOM_BITS 3 `define OR1200_DTLBTR_A_BITS 4 `define OR1200_DTLBTR_D_BITS 5 `define OR1200_DTLBTR_URE_BITS 6 `define OR1200_DTLBTR_UWE_BITS 7 `define OR1200_DTLBTR_SRE_BITS 8 `define OR1200_DTLBTR_SWE_BITS 9 // // DTLB configuration // `define OR1200_DMMU_PS 13 // 13 for 8KB page size `define OR1200_DTLB_INDXW 6 // +5 because of protection bits and CI // // Cache inhibit while DMMU is not enabled/implemented // // cache inhibited 0GB-4GB 1'b1 // cache inhibited 0GB-2GB !dcpu_adr_i[31] // cache inhibited 0GB-1GB 2GB-3GB !dcpu_adr_i[30] // cache inhibited 1GB-2GB 3GB-4GB dcpu_adr_i[30] // cache inhibited 2GB-4GB (default) dcpu_adr_i[31] // cached 0GB-4GB 1'b0 // ////////////////////////////////////////////// // // Insn MMU (IMMU) // // // Address that selects between TLB TR and MR // `define OR1200_ITLB_TM_ADDR 7 // // ITLBMR fields // `define OR1200_ITLBMR_V_BITS 0 // // ITLBTR fields // `define OR1200_ITLBTR_CC_BITS 0 `define OR1200_ITLBTR_CI_BITS 1 `define OR1200_ITLBTR_WBC_BITS 2 `define OR1200_ITLBTR_WOM_BITS 3 `define OR1200_ITLBTR_A_BITS 4 `define OR1200_ITLBTR_D_BITS 5 `define OR1200_ITLBTR_SXE_BITS 6 `define OR1200_ITLBTR_UXE_BITS 7 // // ITLB configuration // `define OR1200_IMMU_PS 13 `define OR1200_ITLB_INDXW 6 // // Cache inhibit while IMMU is not enabled/implemented // Note: all combinations that use icpu_adr_i cause async loop // // cache inhibited 0GB-4GB 1'b1 // cache inhibited 0GB-2GB !icpu_adr_i[31] // cache inhibited 0GB-1GB 2GB-3GB !icpu_adr_i[30] // cache inhibited 1GB-2GB 3GB-4GB icpu_adr_i[30] // cache inhibited 2GB-4GB (default) icpu_adr_i[31] // cached 0GB-4GB 1'b0 // `define OR1200_IMMU_CI 1'b0 ///////////////////////////////////////////////// // // Insn cache (IC) // // 3 for 8 bytes, 4 for 16 bytes etc `define OR1200_ICLS 4 ///////////////////////////////////////////////// // // Data cache (DC) // // 3 for 8 bytes, 4 for 16 bytes etc `define OR1200_DCLS 4 // Define to perform store refill (potential performance penalty) // `define OR1200_DC_STORE_REFILL // // DC configurations `define OR1200_DCSIZE 12 // 4096 `define OR1200_DCTAG_W 21 ///////////////////////////////////////////////// // // Store buffer (SB) // // // Store buffer // // It will improve performance by "caching" CPU stores // using store buffer. This is most important for function // prologues because DC can only work in write though mode // and all stores would have to complete external WB writes // to memory. // Store buffer is between DC and data BIU. // All stores will be stored into store buffer and immediately // completed by the CPU, even though actual external writes // will be performed later. As a consequence store buffer masks // all data bus errors related to stores (data bus errors // related to loads are delivered normally). // All pending CPU loads will wait until store buffer is empty to // ensure strict memory model. Right now this is necessary because // we don't make destinction between cached and cache inhibited // address space, so we simply empty store buffer until loads // can begin. // // It makes design a bit bigger, depending what is the number of // entries in SB FIFO. Number of entries can be changed further // down. // //`define OR1200_SB_IMPLEMENTED // // Number of store buffer entries // // Verified number of entries are 4 and 8 entries // (2 and 3 for OR1200_SB_LOG). OR1200_SB_ENTRIES must // always match 2**OR1200_SB_LOG. // To disable store buffer, undefine // OR1200_SB_IMPLEMENTED. // `define OR1200_SB_LOG 2 // 2 or 3 `define OR1200_SB_ENTRIES 4 // 4 or 8 ///////////////////////////////////////////////// // // Quick Embedded Memory (QMEM) // // // Quick Embedded Memory // // Instantiation of dedicated insn/data memory (RAM or ROM). // Insn fetch has effective throughput 1insn / clock cycle. // Data load takes two clock cycles / access, data store // takes 1 clock cycle / access (if there is no insn fetch)). // Memory instantiation is shared between insn and data, // meaning if insn fetch are performed, data load/store // performance will be lower. // // Main reason for QMEM is to put some time critical functions // into this memory and to have predictable and fast access // to these functions. (soft fpu, context switch, exception // handlers, stack, etc) // // It makes design a bit bigger and slower. QMEM sits behind // IMMU/DMMU so all addresses are physical (so the MMUs can be // used with QMEM and QMEM is seen by the CPU just like any other // memory in the system). IC/DC are sitting behind QMEM so the // whole design timing might be worse with QMEM implemented. // // // Base address defines first address of QMEM. Mask defines // QMEM range in address space. Actual size of QMEM is however // determined with instantiated RAM/ROM. However bigger // mask will reserve more address space for QMEM, but also // make design faster, while more tight mask will take // less address space but also make design slower. If // instantiated RAM/ROM is smaller than space reserved with // the mask, instatiated RAM/ROM will also be shadowed // at higher addresses in reserved space. // `define OR1200_QMEM_IADDR 32'h00800000 `define OR1200_QMEM_IMASK 32'hfff00000 // Max QMEM size 1MB `define OR1200_QMEM_DADDR 32'h00800000 `define OR1200_QMEM_DMASK 32'hfff00000 // Max QMEM size 1MB // // QMEM interface byte-select capability // // To enable qmem_sel* ports, define this macro. // //`define OR1200_QMEM_BSEL // // QMEM interface acknowledge // // To enable qmem_ack port, define this macro. // //`define OR1200_QMEM_ACK ///////////////////////////////////////////////////// // // VR, UPR and Configuration Registers // // // VR, UPR and configuration registers are optional. If // implemented, operating system can automatically figure // out how to use the processor because it knows // what units are available in the processor and how they // are configured. // // This section must be last in or1200_defines.v file so // that all units are already configured and thus // configuration registers are properly set. // Offsets of VR, UPR and CFGR registers `define OR1200_SPRGRP_SYS_VR 4'h0 `define OR1200_SPRGRP_SYS_UPR 4'h1 `define OR1200_SPRGRP_SYS_CPUCFGR 4'h2 `define OR1200_SPRGRP_SYS_DMMUCFGR 4'h3 `define OR1200_SPRGRP_SYS_IMMUCFGR 4'h4 `define OR1200_SPRGRP_SYS_DCCFGR 4'h5 `define OR1200_SPRGRP_SYS_ICCFGR 4'h6 `define OR1200_SPRGRP_SYS_DCFGR 4'h7 // VR fields // VR values `define OR1200_VR_REV 6'h01 `define OR1200_VR_RES1 10'h000 `define OR1200_VR_CFG 8'h00 `define OR1200_VR_VER 8'h12 // UPR values `define OR1200_UPR_UP 1'b1 `define OR1200_UPR_DCP 1'b1 `define OR1200_UPR_ICP 1'b1 `define OR1200_UPR_DMP 1'b1 `define OR1200_UPR_IMP 1'b1 `define OR1200_UPR_MP 1'b1 // MAC always present `define OR1200_UPR_DUP 1'b1 `define OR1200_UPR_PCUP 1'b0 // Performance counters not present `define OR1200_UPR_PMP 1'b1 `define OR1200_UPR_PICP 1'b1 `define OR1200_UPR_TTP 1'b1 `define OR1200_UPR_RES1 13'h0000 `define OR1200_UPR_CUP 8'h00 `define OR1200_CPUCFGR_HGF_BITS 4 `define OR1200_CPUCFGR_OB32S_BITS 5 `define OR1200_CPUCFGR_OB64S_BITS 6 `define OR1200_CPUCFGR_OF32S_BITS 7 `define OR1200_CPUCFGR_OF64S_BITS 8 `define OR1200_CPUCFGR_OV64S_BITS 9 // CPUCFGR values `define OR1200_CPUCFGR_NSGF 4'h0 `define OR1200_CPUCFGR_HGF 1'b0 `define OR1200_CPUCFGR_OB32S 1'b1 `define OR1200_CPUCFGR_OB64S 1'b0 `define OR1200_CPUCFGR_OF32S 1'b0 `define OR1200_CPUCFGR_OF64S 1'b0 `define OR1200_CPUCFGR_OV64S 1'b0 `define OR1200_CPUCFGR_RES1 22'h000000 // DMMUCFGR fields `define OR1200_DMMUCFGR_CRI_BITS 8 `define OR1200_DMMUCFGR_PRI_BITS 9 `define OR1200_DMMUCFGR_TEIRI_BITS 10 `define OR1200_DMMUCFGR_HTR_BITS 11 // DMMUCFGR values `define OR1200_DMMUCFGR_NTW 2'h0 // 1 TLB way `define OR1200_DMMUCFGR_NAE 3'h0 // No ATB entries `define OR1200_DMMUCFGR_CRI 1'b0 // No control register `define OR1200_DMMUCFGR_PRI 1'b0 // No protection reg `define OR1200_DMMUCFGR_TEIRI 1'b1 // TLB entry inv reg impl. `define OR1200_DMMUCFGR_HTR 1'b0 // No HW TLB reload `define OR1200_DMMUCFGR_RES1 20'h00000 // IMMUCFGR fields `define OR1200_IMMUCFGR_CRI_BITS 8 `define OR1200_IMMUCFGR_PRI_BITS 9 `define OR1200_IMMUCFGR_TEIRI_BITS 10 `define OR1200_IMMUCFGR_HTR_BITS 11 // IMMUCFGR values `define OR1200_IMMUCFGR_NTW 2'h0 // 1 TLB way `define OR1200_IMMUCFGR_NAE 3'h0 // No ATB entry `define OR1200_IMMUCFGR_CRI 1'b0 // No control reg `define OR1200_IMMUCFGR_PRI 1'b0 // No protection reg `define OR1200_IMMUCFGR_TEIRI 1'b1 // TLB entry inv reg impl `define OR1200_IMMUCFGR_HTR 1'b0 // No HW TLB reload `define OR1200_IMMUCFGR_RES1 20'h00000 `define OR1200_DCCFGR_CBS_BITS 7 `define OR1200_DCCFGR_CWS_BITS 8 `define OR1200_DCCFGR_CCRI_BITS 9 `define OR1200_DCCFGR_CBIRI_BITS 10 `define OR1200_DCCFGR_CBPRI_BITS 11 `define OR1200_DCCFGR_CBLRI_BITS 12 `define OR1200_DCCFGR_CBFRI_BITS 13 `define OR1200_DCCFGR_CBWBRI_BITS 14 // DCCFGR values `define OR1200_DCCFGR_NCW 3'h0 // 1 cache way `define OR1200_DCCFGR_CWS 1'b0 // Write-through strategy `define OR1200_DCCFGR_CCRI 1'b1 // Cache control reg impl. `define OR1200_DCCFGR_CBIRI 1'b1 // Cache block inv reg impl. `define OR1200_DCCFGR_CBPRI 1'b0 // Cache block prefetch reg not impl. `define OR1200_DCCFGR_CBLRI 1'b0 // Cache block lock reg not impl. `define OR1200_DCCFGR_CBFRI 1'b1 // Cache block flush reg impl. `define OR1200_DCCFGR_CBWBRI 1'b0 // Cache block WB reg not impl. `define OR1200_DCCFGR_RES1 17'h00000 // ICCFGR fields `define OR1200_ICCFGR_CBS_BITS 7 `define OR1200_ICCFGR_CWS_BITS 8 `define OR1200_ICCFGR_CCRI_BITS 9 `define OR1200_ICCFGR_CBIRI_BITS 10 `define OR1200_ICCFGR_CBPRI_BITS 11 `define OR1200_ICCFGR_CBLRI_BITS 12 `define OR1200_ICCFGR_CBFRI_BITS 13 `define OR1200_ICCFGR_CBWBRI_BITS 14 `define OR1200_ICCFGR_NCW 3'h0 // 1 cache way `define OR1200_ICCFGR_CWS 1'b0 // Irrelevant `define OR1200_ICCFGR_CCRI 1'b1 // Cache control reg impl. `define OR1200_ICCFGR_CBIRI 1'b1 // Cache block inv reg impl. `define OR1200_ICCFGR_CBPRI 1'b0 // Cache block prefetch reg not impl. `define OR1200_ICCFGR_CBLRI 1'b0 // Cache block lock reg not impl. `define OR1200_ICCFGR_CBFRI 1'b1 // Cache block flush reg impl. `define OR1200_ICCFGR_CBWBRI 1'b0 // Irrelevant `define OR1200_ICCFGR_RES1 17'h00000 // DCFGR fields `define OR1200_DCFGR_WPCI_BITS 3 // DCFGR values `define OR1200_DCFGR_NDP 3'h0 // Zero DVR/DCR pairs `define OR1200_DCFGR_WPCI 1'b0 // WP counters not impl. `define OR1200_DCFGR_RES1 28'h0000000 module or1200_flat( // or1200_cpu // Clk & Rst clk, rst, // Insn interface ic_en, icpu_adr_o, icpu_cycstb_o, icpu_sel_o, icpu_tag_o, icpu_dat_i, icpu_ack_i, icpu_rty_i, icpu_err_i, icpu_adr_i, icpu_tag_i, immu_en, // Debug unit ex_insn, ex_freeze, id_pc, branch_op, spr_dat_npc, rf_dataw, du_stall, du_addr, du_dat_du, du_read, du_write, du_dsr, du_hwbkpt, du_except, du_dat_cpu, // Data interface dc_en, dcpu_adr_o, dcpu_cycstb_o, dcpu_we_o, dcpu_sel_o, dcpu_tag_o, dcpu_dat_o, dcpu_dat_i, dcpu_ack_i, dcpu_rty_i, dcpu_err_i, dcpu_tag_i, dmmu_en, // Interrupt & tick exceptions sig_int, sig_tick, // SPR interface supv, spr_addr, spr_dat_cpu, spr_dat_pic, spr_dat_tt, spr_dat_pm, spr_dat_dmmu, spr_dat_immu, spr_dat_du, spr_cs, spr_we ); //parameter dw = `OR1200_OPERAND_WIDTH; //parameter aw = `OR1200_REGFILE_ADDR_WIDTH; // // I/O ports // // // Clk & Rst // input clk; input rst; // // Insn (IC) interface // output ic_en; output [31:0] icpu_adr_o; output icpu_cycstb_o; output [3:0] icpu_sel_o; output [3:0] icpu_tag_o; input [31:0] icpu_dat_i; input icpu_ack_i; input icpu_rty_i; input icpu_err_i; input [31:0] icpu_adr_i; input [3:0] icpu_tag_i; // // Insn (IMMU) interface // output immu_en; // // Debug interface // output [31:0] ex_insn; output ex_freeze; output [31:0] id_pc; output [`OR1200_BRANCHOP_WIDTH-1:0] branch_op; input du_stall; input [`OR1200_OPERAND_WIDTH-1:0] du_addr; input [`OR1200_OPERAND_WIDTH-1:0] du_dat_du; input du_read; input du_write; input [`OR1200_DU_DSR_WIDTH-1:0] du_dsr; input du_hwbkpt; output [12:0] du_except; output [`OR1200_OPERAND_WIDTH-1:0] du_dat_cpu; output [`OR1200_OPERAND_WIDTH-1:0] rf_dataw; // // Data (DC) interface // output [31:0] dcpu_adr_o; output dcpu_cycstb_o; output dcpu_we_o; output [3:0] dcpu_sel_o; output [3:0] dcpu_tag_o; output [31:0] dcpu_dat_o; input [31:0] dcpu_dat_i; input dcpu_ack_i; input dcpu_rty_i; input dcpu_err_i; input [3:0] dcpu_tag_i; output dc_en; // // Data (DMMU) interface // output dmmu_en; // // SPR interface // output supv; input [`OR1200_OPERAND_WIDTH-1:0] spr_dat_pic; input [`OR1200_OPERAND_WIDTH-1:0] spr_dat_tt; input [`OR1200_OPERAND_WIDTH-1:0] spr_dat_pm; input [`OR1200_OPERAND_WIDTH-1:0] spr_dat_dmmu; input [`OR1200_OPERAND_WIDTH-1:0] spr_dat_immu; input [`OR1200_OPERAND_WIDTH-1:0] spr_dat_du; output [`OR1200_OPERAND_WIDTH-1:0] spr_addr; output [`OR1200_OPERAND_WIDTH-1:0] spr_dat_cpu; output [`OR1200_OPERAND_WIDTH-1:0] spr_dat_npc; output [31:0] spr_cs; output spr_we; // // Interrupt exceptions // input sig_int; input sig_tick; // // Internal wires // wire [31:0] if_insn; wire [31:0] if_pc; wire [31:2] lr_sav; wire [`OR1200_REGFILE_ADDR_WIDTH-1:0] rf_addrw; wire [`OR1200_REGFILE_ADDR_WIDTH-1:0] rf_addra; wire [`OR1200_REGFILE_ADDR_WIDTH-1:0] rf_addrb; wire rf_rda; wire rf_rdb; wire [`OR1200_OPERAND_WIDTH-1:0] simm; wire [`OR1200_OPERAND_WIDTH-1:2] branch_addrofs; wire [`OR1200_ALUOP_WIDTH-1:0] alu_op; wire [`OR1200_SHROTOP_WIDTH-1:0] shrot_op; wire [`OR1200_COMPOP_WIDTH-1:0] comp_op; wire [`OR1200_BRANCHOP_WIDTH-1:0] branch_op; wire [`OR1200_LSUOP_WIDTH-1:0] lsu_op; wire genpc_freeze; wire if_freeze; wire id_freeze; wire ex_freeze; wire wb_freeze; wire [`OR1200_SEL_WIDTH-1:0] sel_a; wire [`OR1200_SEL_WIDTH-1:0] sel_b; wire [`OR1200_RFWBOP_WIDTH-1:0] rfwb_op; wire [`OR1200_OPERAND_WIDTH-1:0] rf_dataw; wire [`OR1200_OPERAND_WIDTH-1:0] rf_dataa; wire [`OR1200_OPERAND_WIDTH-1:0] rf_datab; wire [`OR1200_OPERAND_WIDTH-1:0] muxed_b; wire [`OR1200_OPERAND_WIDTH-1:0] wb_forw; wire wbforw_valid; wire [`OR1200_OPERAND_WIDTH-1:0] operand_a; wire [`OR1200_OPERAND_WIDTH-1:0] operand_b; wire [`OR1200_OPERAND_WIDTH-1:0] alu_dataout; wire [`OR1200_OPERAND_WIDTH-1:0] lsu_dataout; wire [`OR1200_OPERAND_WIDTH-1:0] sprs_dataout; wire [31:0] lsu_addrofs; wire [`OR1200_MULTICYCLE_WIDTH-1:0] multicycle; wire [`OR1200_EXCEPT_WIDTH-1:0] except_type; wire [4:0] cust5_op; wire [5:0] cust5_limm; wire flushpipe; wire extend_flush; wire branch_taken; wire flag; wire flagforw; wire flag_we; wire k_carry; wire cyforw; wire cy_we; wire lsu_stall; wire epcr_we; wire eear_we; wire esr_we; wire pc_we; wire [31:0] epcr; wire [31:0] eear; wire [`OR1200_SR_WIDTH-1:0] esr; wire sr_we; wire [`OR1200_SR_WIDTH-1:0] to_sr; wire [`OR1200_SR_WIDTH-1:0] sr; wire except_start; wire except_started; wire [31:0] wb_insn; wire [15:0] spr_addrimm; wire sig_syscall; wire sig_trap; wire [31:0] spr_dat_cfgr; wire [31:0] spr_dat_rf; wire [31:0] spr_dat_npc; wire [31:0] spr_dat_ppc; wire [31:0] spr_dat_mac; wire force_dslot_fetch; wire no_more_dslot; wire ex_void; wire if_stall; wire id_macrc_op; wire ex_macrc_op; wire [`OR1200_MACOP_WIDTH-1:0] mac_op; wire [31:0] mult_mac_result; wire mac_stall; wire [12:0] except_stop; wire genpc_refetch; wire rfe; wire lsu_unstall; wire except_align; wire except_dtlbmiss; wire except_dmmufault; wire except_illegal; wire except_itlbmiss; wire except_immufault; wire except_ibuserr; wire except_dbuserr; wire abort_ex; // // Send exceptions to Debug Unit // assign du_except = except_stop; // // Data cache enable // assign dc_en = sr[`OR1200_SR_DCE]; // // Instruction cache enable // assign ic_en = sr[`OR1200_SR_ICE]; // // DMMU enable // assign dmmu_en = sr[`OR1200_SR_DME]; // // IMMU enable // assign immu_en = sr[`OR1200_SR_IME]; // // SUPV bit // assign supv = sr[`OR1200_SR_SM]; // // Instantiation of instruction fetch block // or1200_genpc or1200_genpc( .clk(clk), .rst(rst), .icpu_adr_o(icpu_adr_o), .icpu_cycstb_o(icpu_cycstb_o), .icpu_sel_o(icpu_sel_o), .icpu_tag_o(icpu_tag_o), .icpu_rty_i(icpu_rty_i), .icpu_adr_i(icpu_adr_i), .branch_op(branch_op), .except_type(except_type), .except_start(except_start), .except_prefix(sr[`OR1200_SR_EPH]), .branch_addrofs(branch_addrofs), .lr_restor(operand_b), .flag(flag), .taken(branch_taken), .binsn_addr(lr_sav), .epcr(epcr), .spr_dat_i(spr_dat_cpu), .spr_pc_we(pc_we), .genpc_refetch(genpc_refetch), .genpc_freeze(genpc_freeze), .genpc_stop_prefetch(1'b0), .no_more_dslot(no_more_dslot) ); // // Instantiation of instruction fetch block // or1200_if or1200_if( .clk(clk), .rst(rst), .icpu_dat_i(icpu_dat_i), .icpu_ack_i(icpu_ack_i), .icpu_err_i(icpu_err_i), .icpu_adr_i(icpu_adr_i), .icpu_tag_i(icpu_tag_i), .if_freeze(if_freeze), .if_insn(if_insn), .if_pc(if_pc), .flushpipe(flushpipe), .if_stall(if_stall), .no_more_dslot(no_more_dslot), .genpc_refetch(genpc_refetch), .rfe(rfe), .except_itlbmiss(except_itlbmiss), .except_immufault(except_immufault), .except_ibuserr(except_ibuserr) ); // // Instantiation of instruction decode/control logic // or1200_ctrl or1200_ctrl( .clk(clk), .rst(rst), .id_freeze(id_freeze), .ex_freeze(ex_freeze), .wb_freeze(wb_freeze), .flushpipe(flushpipe), .if_insn(if_insn), .ex_insn(ex_insn), .branch_op(branch_op), .branch_taken(branch_taken), .rf_addra(rf_addra), .rf_addrb(rf_addrb), .rf_rda(rf_rda), .rf_rdb(rf_rdb), .alu_op(alu_op), .mac_op(mac_op), .shrot_op(shrot_op), .comp_op(comp_op), .rf_addrw(rf_addrw), .rfwb_op(rfwb_op), .wb_insn(wb_insn), .simm(simm), .branch_addrofs(branch_addrofs), .lsu_addrofs(lsu_addrofs), .sel_a(sel_a), .sel_b(sel_b), .lsu_op(lsu_op), .cust5_op(cust5_op), .cust5_limm(cust5_limm), .multicycle(multicycle), .spr_addrimm(spr_addrimm), .wbforw_valid(wbforw_valid), .sig_syscall(sig_syscall), .sig_trap(sig_trap), .force_dslot_fetch(force_dslot_fetch), .no_more_dslot(no_more_dslot), .ex_void(ex_void), .id_macrc_op(id_macrc_op), .ex_macrc_op(ex_macrc_op), .rfe(rfe), .du_hwbkpt(du_hwbkpt), .except_illegal(except_illegal) ); // // Instantiation of register file // or1200_rf or1200_rf( .clk(clk), .rst(rst), .supv(sr[`OR1200_SR_SM]), .wb_freeze(wb_freeze), .addrw(rf_addrw), .dataw(rf_dataw), .id_freeze(id_freeze), .we(rfwb_op[0]), .flushpipe(flushpipe), .addra(rf_addra), .rda(rf_rda), .dataa(rf_dataa), .addrb(rf_addrb), .rdb(rf_rdb), .datab(rf_datab), .spr_cs(spr_cs[`OR1200_SPR_GROUP_SYS]), .spr_write(spr_we), .spr_addr(spr_addr), .spr_dat_i(spr_dat_cpu), .spr_dat_o(spr_dat_rf) ); // // Instantiation of operand muxes // or1200_operandmuxes or1200_operandmuxes( .clk(clk), .rst(rst), .id_freeze(id_freeze), .ex_freeze(ex_freeze), .rf_dataa(rf_dataa), .rf_datab(rf_datab), .ex_forw(rf_dataw), .wb_forw(wb_forw), .simm(simm), .sel_a(sel_a), .sel_b(sel_b), .operand_a(operand_a), .operand_b(operand_b), .muxed_b(muxed_b) ); // // Instantiation of CPU's ALU // or1200_alu or1200_alu( .a(operand_a), .b(operand_b), .mult_mac_result(mult_mac_result), .macrc_op(ex_macrc_op), .alu_op(alu_op), .shrot_op(shrot_op), .comp_op(comp_op), .cust5_op(cust5_op), .cust5_limm(cust5_limm), .result(alu_dataout), .flagforw(flagforw), .flag_we(flag_we), .cyforw(cyforw), .cy_we(cy_we), .flag(flag), .k_carry(k_carry) ); // // Instantiation of CPU's ALU // or1200_mult_mac or1200_mult_mac( .clk(clk), .rst(rst), .ex_freeze(ex_freeze), .id_macrc_op(id_macrc_op), .macrc_op(ex_macrc_op), .a(operand_a), .b(operand_b), .mac_op(mac_op), .alu_op(alu_op), .result(mult_mac_result), .mac_stall_r(mac_stall), .spr_cs(spr_cs[`OR1200_SPR_GROUP_MAC]), .spr_write(spr_we), .spr_addr(spr_addr), .spr_dat_i(spr_dat_cpu), .spr_dat_o(spr_dat_mac) ); // // Instantiation of CPU's SPRS block // or1200_sprs or1200_sprs( .clk(clk), .rst(rst), .addrbase(operand_a), .addrofs(spr_addrimm), .dat_i(operand_b), .alu_op(alu_op), .flagforw(flagforw), .flag_we(flag_we), .flag(flag), .cyforw(cyforw), .cy_we(cy_we), .carry(k_carry), .to_wbmux(sprs_dataout), .du_addr(du_addr), .du_dat_du(du_dat_du), .du_read(du_read), .du_write(du_write), .du_dat_cpu(du_dat_cpu), .spr_addr(spr_addr), .spr_dat_pic(spr_dat_pic), .spr_dat_tt(spr_dat_tt), .spr_dat_pm(spr_dat_pm), .spr_dat_cfgr(spr_dat_cfgr), .spr_dat_rf(spr_dat_rf), .spr_dat_npc(spr_dat_npc), .spr_dat_ppc(spr_dat_ppc), .spr_dat_mac(spr_dat_mac), .spr_dat_dmmu(spr_dat_dmmu), .spr_dat_immu(spr_dat_immu), .spr_dat_du(spr_dat_du), .spr_dat_o(spr_dat_cpu), .spr_cs(spr_cs), .spr_we(spr_we), .epcr_we(epcr_we), .eear_we(eear_we), .esr_we(esr_we), .pc_we(pc_we), .epcr(epcr), .eear(eear), .esr(esr), .except_started(except_started), .sr_we(sr_we), .to_sr(to_sr), .sr(sr), .branch_op(branch_op) ); // // Instantiation of load/store unit // or1200_lsu or1200_lsu( .addrbase(operand_a), .addrofs(lsu_addrofs), .lsu_op(lsu_op), .lsu_datain(operand_b), .lsu_dataout(lsu_dataout), .lsu_stall(lsu_stall), .lsu_unstall(lsu_unstall), .du_stall(du_stall), .except_align(except_align), .except_dtlbmiss(except_dtlbmiss), .except_dmmufault(except_dmmufault), .except_dbuserr(except_dbuserr), .dcpu_adr_o(dcpu_adr_o), .dcpu_cycstb_o(dcpu_cycstb_o), .dcpu_we_o(dcpu_we_o), .dcpu_sel_o(dcpu_sel_o), .dcpu_tag_o(dcpu_tag_o), .dcpu_dat_o(dcpu_dat_o), .dcpu_dat_i(dcpu_dat_i), .dcpu_ack_i(dcpu_ack_i), .dcpu_rty_i(dcpu_rty_i), .dcpu_err_i(dcpu_err_i), .dcpu_tag_i(dcpu_tag_i) ); // // Instantiation of write-back muxes // or1200_wbmux or1200_wbmux( .clk(clk), .rst(rst), .wb_freeze(wb_freeze), .rfwb_op(rfwb_op), .muxin_a(alu_dataout), .muxin_b(lsu_dataout), .muxin_c(sprs_dataout), .muxin_d({lr_sav, 2'b0}), .muxout(rf_dataw), .muxreg(wb_forw), .muxreg_valid(wbforw_valid) ); // // Instantiation of freeze logic // or1200_freeze or1200_freeze( .clk(clk), .rst(rst), .multicycle(multicycle), .flushpipe(flushpipe), .extend_flush(extend_flush), .lsu_stall(lsu_stall), .if_stall(if_stall), .lsu_unstall(lsu_unstall), .force_dslot_fetch(force_dslot_fetch), .abort_ex(abort_ex), .du_stall(du_stall), .mac_stall(mac_stall), .genpc_freeze(genpc_freeze), .if_freeze(if_freeze), .id_freeze(id_freeze), .ex_freeze(ex_freeze), .wb_freeze(wb_freeze), .icpu_ack_i(icpu_ack_i), .icpu_err_i(icpu_err_i) ); // // Instantiation of exception block // or1200_except or1200_except( .clk(clk), .rst(rst), .sig_ibuserr(except_ibuserr), .sig_dbuserr(except_dbuserr), .sig_illegal(except_illegal), .sig_align(except_align), .sig_range(1'b0), .sig_dtlbmiss(except_dtlbmiss), .sig_dmmufault(except_dmmufault), .sig_int(sig_int), .sig_syscall(sig_syscall), .sig_trap(sig_trap), .sig_itlbmiss(except_itlbmiss), .sig_immufault(except_immufault), .sig_tick(sig_tick), .branch_taken(branch_taken), .icpu_ack_i(icpu_ack_i), .icpu_err_i(icpu_err_i), .dcpu_ack_i(dcpu_ack_i), .dcpu_err_i(dcpu_err_i), .genpc_freeze(genpc_freeze), .id_freeze(id_freeze), .ex_freeze(ex_freeze), .wb_freeze(wb_freeze), .if_stall(if_stall), .if_pc(if_pc), .id_pc(id_pc), .lr_sav(lr_sav), .flushpipe(flushpipe), .extend_flush(extend_flush), .except_type(except_type), .except_start(except_start), .except_started(except_started), .except_stop(except_stop), .ex_void(ex_void), .spr_dat_ppc(spr_dat_ppc), .spr_dat_npc(spr_dat_npc), .datain(operand_b), .du_dsr(du_dsr), .epcr_we(epcr_we), .eear_we(eear_we), .esr_we(esr_we), .pc_we(pc_we), .epcr(epcr), .eear(eear), .esr(esr), .lsu_addr(dcpu_adr_o), .sr_we(sr_we), .to_sr(to_sr), .sr(sr), .abort_ex(abort_ex) ); // // Instantiation of configuration registers // or1200_cfgr or1200_cfgr( .spr_addr(spr_addr), .spr_dat_o(spr_dat_cfgr) ); endmodule `define OR1200_ITAG_IDLE 4'h0 // idle bus `define OR1200_ITAG_NI 4'h1 // normal insn `define OR1200_ITAG_BE 4'hb // Bus error exception `define OR1200_ITAG_PE 4'hc // Page fault exception `define OR1200_ITAG_TE 4'hd // TLB miss exception `define OR1200_BRANCHOP_WIDTH 3 `define OR1200_BRANCHOP_NOP 3'b000 `define OR1200_BRANCHOP_J 3'b001 `define OR1200_BRANCHOP_JR 3'b010 `define OR1200_BRANCHOP_BAL 3'b011 `define OR1200_BRANCHOP_BF 3'b100 `define OR1200_BRANCHOP_BNF 3'b101 `define OR1200_BRANCHOP_RFE 3'b110 `define OR1200_EXCEPT_WIDTH 4 `define OR1200_EXCEPT_EPH0_P 20'h00000 `define OR1200_EXCEPT_EPH1_P 20'hF0000 `define OR1200_EXCEPT_V 8'h00 module or1200_genpc( // Clock and reset clk, rst, // External i/f to IC icpu_adr_o, icpu_cycstb_o, icpu_sel_o, icpu_tag_o, icpu_rty_i, icpu_adr_i, // Internal i/f branch_op, except_type,except_start, except_prefix, branch_addrofs, lr_restor, flag, taken, binsn_addr, epcr, spr_dat_i, spr_pc_we, genpc_refetch, genpc_freeze, genpc_stop_prefetch, no_more_dslot ); // // I/O // // // Clock and reset // input clk; input rst; // // External i/f to IC // output [31:0] icpu_adr_o; output icpu_cycstb_o; output [3:0] icpu_sel_o; output [3:0] icpu_tag_o; input icpu_rty_i; input [31:0] icpu_adr_i; // // Internal i/f // input [`OR1200_BRANCHOP_WIDTH-1:0] branch_op; input [`OR1200_EXCEPT_WIDTH-1:0] except_type; input except_start; input except_prefix; input [31:2] branch_addrofs; input [31:0] lr_restor; input flag; output taken; input [31:2] binsn_addr; input [31:0] epcr; input [31:0] spr_dat_i; input spr_pc_we; input genpc_refetch; input genpc_freeze; input genpc_stop_prefetch; input no_more_dslot; // // Internal wires and regs // reg [31:2] pcreg; reg [31:0] pc; reg taken; /* Set to in case of jump or taken branch */ reg genpc_refetch_r; // // Address of insn to be fecthed // assign icpu_adr_o = !no_more_dslot & !except_start & !spr_pc_we & (icpu_rty_i | genpc_refetch) ? icpu_adr_i : pc; // assign icpu_adr_o = !except_start & !spr_pc_we & (icpu_rty_i | genpc_refetch) ? icpu_adr_i : pc; // // Control access to IC subsystem // // assign icpu_cycstb_o = !genpc_freeze & !no_more_dslot; assign icpu_cycstb_o = !genpc_freeze; // works, except remaining raised cycstb during long load/store //assign icpu_cycstb_o = !(genpc_freeze | genpc_refetch & genpc_refetch_r); //assign icpu_cycstb_o = !(genpc_freeze | genpc_stop_prefetch); assign icpu_sel_o = 4'b1111; assign icpu_tag_o = `OR1200_ITAG_NI; // // genpc_freeze_r // always @(posedge clk ) if (rst) genpc_refetch_r <= 1'b0; else if (genpc_refetch) genpc_refetch_r <= 1'b1; else genpc_refetch_r <= 1'b0; // // Async calculation of new PC value. This value is used for addressing the IC. // always @(pcreg or branch_addrofs or binsn_addr or flag or branch_op or except_type or except_start or lr_restor or epcr or spr_pc_we or spr_dat_i or except_prefix) begin case ({spr_pc_we, except_start, branch_op}) // synopsys parallel_case {2'b00, `OR1200_BRANCHOP_NOP}: begin pc = {pcreg + 30'b000000000000000000000000000001, 2'b0}; taken = 1'b0; end {2'b00, `OR1200_BRANCHOP_J}: begin pc = {branch_addrofs, 2'b0}; taken = 1'b1; end {2'b00, `OR1200_BRANCHOP_JR}: begin pc = lr_restor; taken = 1'b1; end {2'b00, `OR1200_BRANCHOP_BAL}: begin pc = {binsn_addr + branch_addrofs, 2'b0}; taken = 1'b1; end {2'b00, `OR1200_BRANCHOP_BF}: if (flag) begin pc = {binsn_addr + branch_addrofs, 2'b0}; taken = 1'b1; end else begin pc = {pcreg + 30'b000000000000000000000000000001, 2'b0}; taken = 1'b0; end {2'b00, `OR1200_BRANCHOP_BNF}: if (flag) begin pc = {pcreg + 30'b000000000000000000000000000001, 2'b0}; taken = 1'b0; end else begin pc = {binsn_addr + branch_addrofs, 2'b0}; taken = 1'b1; end {2'b00, `OR1200_BRANCHOP_RFE}: begin pc = epcr; taken = 1'b1; end {2'b01, 3'b000}: begin pc = {(except_prefix ? `OR1200_EXCEPT_EPH1_P : `OR1200_EXCEPT_EPH0_P), except_type, `OR1200_EXCEPT_V}; taken = 1'b1; end {2'b01, 3'b001}: begin pc = {(except_prefix ? `OR1200_EXCEPT_EPH1_P : `OR1200_EXCEPT_EPH0_P), except_type, `OR1200_EXCEPT_V}; taken = 1'b1; end {2'b01, 3'b010}: begin pc = {(except_prefix ? `OR1200_EXCEPT_EPH1_P : `OR1200_EXCEPT_EPH0_P), except_type, `OR1200_EXCEPT_V}; taken = 1'b1; end {2'b01, 3'b011}: begin pc = {(except_prefix ? `OR1200_EXCEPT_EPH1_P : `OR1200_EXCEPT_EPH0_P), except_type, `OR1200_EXCEPT_V}; taken = 1'b1; end {2'b01, 3'b100}: begin pc = {(except_prefix ? `OR1200_EXCEPT_EPH1_P : `OR1200_EXCEPT_EPH0_P), except_type, `OR1200_EXCEPT_V}; taken = 1'b1; end {2'b01, 3'b101}: begin pc = {(except_prefix ? `OR1200_EXCEPT_EPH1_P : `OR1200_EXCEPT_EPH0_P), except_type, `OR1200_EXCEPT_V}; taken = 1'b1; end {2'b01, 3'b110}: begin pc = {(except_prefix ? `OR1200_EXCEPT_EPH1_P : `OR1200_EXCEPT_EPH0_P), except_type, `OR1200_EXCEPT_V}; taken = 1'b1; end {2'b01, 3'b111}: begin pc = {(except_prefix ? `OR1200_EXCEPT_EPH1_P : `OR1200_EXCEPT_EPH0_P), except_type, `OR1200_EXCEPT_V}; taken = 1'b1; end default: begin pc = spr_dat_i; taken = 1'b0; end endcase end // // PC register // always @(posedge clk ) if (rst) // pcreg <= 30'd63; pcreg <= ({(except_prefix ? `OR1200_EXCEPT_EPH1_P : `OR1200_EXCEPT_EPH0_P),8'b11111111, `OR1200_EXCEPT_V} - 1) >> 2; else if (spr_pc_we) pcreg <= spr_dat_i[31:2]; else if (no_more_dslot | except_start | !genpc_freeze & !icpu_rty_i & !genpc_refetch) // else if (except_start | !genpc_freeze & !icpu_rty_i & !genpc_refetch) pcreg <= pc[31:2]; wire unused; assign unused = |except_prefix & | binsn_addr | genpc_stop_prefetch ; endmodule `define OR1200_ITAG_IDLE 4'h0 // idle bus `define OR1200_ITAG_NI 4'h1 // normal insn `define OR1200_ITAG_BE 4'hb // Bus error exception `define OR1200_ITAG_PE 4'hc // Page fault exception `define OR1200_ITAG_TE 4'hd // TLB miss exception `define OR1200_OR32_J 6'b000000 `define OR1200_OR32_JAL 6'b000001 `define OR1200_OR32_BNF 6'b000011 `define OR1200_OR32_BF 6'b000100 `define OR1200_OR32_NOP 6'b000101 `define OR1200_OR32_MOVHI 6'b000110 `define OR1200_OR32_XSYNC 6'b001000 `define OR1200_OR32_RFE 6'b001001 /* */ `define OR1200_OR32_JR 6'b010001 `define OR1200_OR32_JALR 6'b010010 `define OR1200_OR32_MACI 6'b010011 /* */ `define OR1200_OR32_LWZ 6'b100001 `define OR1200_OR32_LBZ 6'b100011 `define OR1200_OR32_LBS 6'b100100 `define OR1200_OR32_LHZ 6'b100101 `define OR1200_OR32_LHS 6'b100110 `define OR1200_OR32_ADDI 6'b100111 `define OR1200_OR32_ADDIC 6'b101000 `define OR1200_OR32_ANDI 6'b101001 `define OR1200_OR32_ORI 6'b101010 `define OR1200_OR32_XORI 6'b101011 `define OR1200_OR32_MULI 6'b101100 `define OR1200_OR32_MFSPR 6'b101101 `define OR1200_OR32_SH_ROTI 6'b101110 `define OR1200_OR32_SFXXI 6'b101111 /* */ `define OR1200_OR32_MTSPR 6'b110000 `define OR1200_OR32_MACMSB 6'b110001 /* */ `define OR1200_OR32_SW 6'b110101 `define OR1200_OR32_SB 6'b110110 `define OR1200_OR32_SH 6'b110111 `define OR1200_OR32_ALU 6'b111000 `define OR1200_OR32_SFXX 6'b111001 //`define OR1200_OR32_CUST5 6'b111100 module or1200_if( // Clock and reset clk, rst, // External i/f to IC icpu_dat_i, icpu_ack_i, icpu_err_i, icpu_adr_i, icpu_tag_i, // Internal i/f if_freeze, if_insn, if_pc, flushpipe, if_stall, no_more_dslot, genpc_refetch, rfe, except_itlbmiss, except_immufault, except_ibuserr ); // // I/O // // // Clock and reset // input clk; input rst; // // External i/f to IC // input [31:0] icpu_dat_i; input icpu_ack_i; input icpu_err_i; input [31:0] icpu_adr_i; input [3:0] icpu_tag_i; // // Internal i/f // input if_freeze; output [31:0] if_insn; output [31:0] if_pc; input flushpipe; output if_stall; input no_more_dslot; output genpc_refetch; input rfe; output except_itlbmiss; output except_immufault; output except_ibuserr; // // Internal wires and regs // reg [31:0] insn_saved; reg [31:0] addr_saved; reg saved; // // IF stage insn // assign if_insn = icpu_err_i | no_more_dslot | rfe ? {`OR1200_OR32_NOP, 26'h0410000} : saved ? insn_saved : icpu_ack_i ? icpu_dat_i : {`OR1200_OR32_NOP, 26'h0610000}; assign if_pc = saved ? addr_saved : icpu_adr_i; // assign if_stall = !icpu_err_i & !icpu_ack_i & !saved & !no_more_dslot; assign if_stall = !icpu_err_i & !icpu_ack_i & !saved; assign genpc_refetch = saved & icpu_ack_i; assign except_itlbmiss = icpu_err_i & (icpu_tag_i == `OR1200_ITAG_TE) & !no_more_dslot; assign except_immufault = icpu_err_i & (icpu_tag_i == `OR1200_ITAG_PE) & !no_more_dslot; assign except_ibuserr = icpu_err_i & (icpu_tag_i == `OR1200_ITAG_BE) & !no_more_dslot; // // Flag for saved insn/address // always @(posedge clk ) if (rst) saved <= 1'b0; else if (flushpipe) saved <= 1'b0; else if (icpu_ack_i & if_freeze & !saved) saved <= 1'b1; else if (!if_freeze) saved <= 1'b0; // // Store fetched instruction // always @(posedge clk ) if (rst) insn_saved <= {`OR1200_OR32_NOP, 26'h0410000}; else if (flushpipe) insn_saved <= {`OR1200_OR32_NOP, 26'h0410000}; else if (icpu_ack_i & if_freeze & !saved) insn_saved <= icpu_dat_i; else if (!if_freeze) insn_saved <= {`OR1200_OR32_NOP, 26'h0410000}; // // Store fetched instruction's address // always @(posedge clk ) if (rst) addr_saved <= 32'h00000000; else if (flushpipe) addr_saved <= 32'h00000000; else if (icpu_ack_i & if_freeze & !saved) addr_saved <= icpu_adr_i; else if (!if_freeze) addr_saved <= icpu_adr_i; endmodule ////////////////////////////////////////////////////////////////////// //// //// //// OR1200's Instruction decode //// //// //// //// This file is part of the OpenRISC 1200 project //// //// http://www.opencores.org/cores/or1k/ //// //// //// //// Description //// //// Majority of instruction decoding is performed here. //// //// //// //// To Do: //// //// - make it smaller and faster //// //// //// //// Author(s): //// //// - Damjan Lampret, lampret@opencores.org //// //// //// ////////////////////////////////////////////////////////////////////// //// //// //// Copyright (C) 2000 Authors and OPENCORES.ORG //// //// //// //// This source file may be used and distributed without //// //// restriction provided that this copyright statement is not //// //// removed from the file and that any derivative work contains //// //// the original copyright notice and the associated disclaimer. //// //// //// //// This source file is free software; you can redistribute it //// //// and/or modify it under the terms of the GNU Lesser General //// //// Public License as published by the Free Software Foundation; //// //// either version 2.1 of the License, or (at your option) any //// //// later version. //// //// //// //// This source is distributed in the hope that it will be //// //// useful, but WITHOUT ANY WARRANTY; without even the implied //// //// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// //// PURPOSE. See the GNU Lesser General Public License for more //// //// details. //// //// //// //// You should have received a copy of the GNU Lesser General //// //// Public License along with this source; if not, download it //// //// from http://www.opencores.org/lgpl.shtml //// //// //// ////////////////////////////////////////////////////////////////////// // // CVS Revision History // // $Log: not supported by cvs2svn $ // Revision 1.12 2005/01/07 09:31:07 andreje // sign/zero extension for l.sfxxi instructions corrected // // Revision 1.11 2004/06/08 18:17:36 lampret // Non-functional changes. Coding style fixes. // // Revision 1.10 2004/05/09 19:49:04 lampret // Added some l.cust5 custom instructions as example // // Revision 1.9 2004/04/05 08:29:57 lampret // Merged branch_qmem into main tree. // // Revision 1.8.4.1 2004/02/11 01:40:11 lampret // preliminary HW breakpoints support in debug unit (by default disabled). To enable define OR1200_DU_HWBKPTS. // // Revision 1.8 2003/04/24 00:16:07 lampret // No functional changes. Added defines to disable implementation of multiplier/MAC // // Revision 1.7 2002/09/07 05:42:02 lampret // Added optional SR[CY]. Added define to enable additional (compare) flag modifiers. Defines are OR1200_IMPL_ADDC and OR1200_ADDITIONAL_FLAG_MODIFIERS. // // Revision 1.6 2002/03/29 15:16:54 lampret // Some of the warnings fixed. // // Revision 1.5 2002/02/01 19:56:54 lampret // Fixed combinational loops. // // Revision 1.4 2002/01/28 01:15:59 lampret // Changed 'void' nop-ops instead of insn[0] to use insn[16]. Debug unit stalls the tick timer. Prepared new flag generation for add and and insns. Blocked DC/IC while they are turned off. Fixed I/D MMU SPRs layout except WAYs. TODO: smart IC invalidate, l.j 2 and TLB ways. // // Revision 1.3 2002/01/18 14:21:43 lampret // Fixed 'the NPC single-step fix'. // // Revision 1.2 2002/01/14 06:18:22 lampret // Fixed mem2reg bug in FAST implementation. Updated debug unit to work with new genpc/if. // // Revision 1.1 2002/01/03 08:16:15 lampret // New prefixes for RTL files, prefixed module names. Updated cache controllers and MMUs. // // Revision 1.14 2001/11/30 18:59:17 simons // force_dslot_fetch does not work - allways zero. // // Revision 1.13 2001/11/20 18:46:15 simons // Break point bug fixed // // Revision 1.12 2001/11/18 08:36:28 lampret // For GDB changed single stepping and disabled trap exception. // // Revision 1.11 2001/11/13 10:02:21 lampret // Added 'setpc'. Renamed some signals (except_flushpipe into flushpipe etc) // // Revision 1.10 2001/11/12 01:45:40 lampret // Moved flag bit into SR. Changed RF enable from constant enable to dynamic enable for read ports. // // Revision 1.9 2001/11/10 03:43:57 lampret // Fixed exceptions. // // Revision 1.8 2001/10/21 17:57:16 lampret // Removed params from generic_XX.v. Added translate_off/on in sprs.v and id.v. Removed spr_addr from dc.v and ic.v. Fixed CR+LF. // // Revision 1.7 2001/10/14 13:12:09 lampret // MP3 version. // // Revision 1.1.1.1 2001/10/06 10:18:36 igorm // no message // // Revision 1.2 2001/08/13 03:36:20 lampret // Added cfg regs. Moved all defines into one defines.v file. More cleanup. // // Revision 1.1 2001/08/09 13:39:33 lampret // Major clean-up. // // module or1200_ctrl( // Clock and reset clk, rst, // Internal i/f id_freeze, ex_freeze, wb_freeze, flushpipe, if_insn, ex_insn, branch_op, branch_taken, rf_addra, rf_addrb, rf_rda, rf_rdb, alu_op, mac_op, shrot_op, comp_op, rf_addrw, rfwb_op, wb_insn, simm, branch_addrofs, lsu_addrofs, sel_a, sel_b, lsu_op, cust5_op, cust5_limm, multicycle, spr_addrimm, wbforw_valid, sig_syscall, sig_trap, force_dslot_fetch, no_more_dslot, ex_void, id_macrc_op, ex_macrc_op, rfe,du_hwbkpt, except_illegal ); // // I/O // input clk; input rst; input id_freeze; input ex_freeze; input wb_freeze; input flushpipe; input [31:0] if_insn; output [31:0] ex_insn; output [`OR1200_BRANCHOP_WIDTH-1:0] branch_op; input branch_taken; output [`OR1200_REGFILE_ADDR_WIDTH-1:0] rf_addrw; output [`OR1200_REGFILE_ADDR_WIDTH-1:0] rf_addra; output [`OR1200_REGFILE_ADDR_WIDTH-1:0] rf_addrb; output rf_rda; output rf_rdb; output [`OR1200_ALUOP_WIDTH-1:0] alu_op; output [`OR1200_MACOP_WIDTH-1:0] mac_op; output [`OR1200_SHROTOP_WIDTH-1:0] shrot_op; output [`OR1200_RFWBOP_WIDTH-1:0] rfwb_op; output [31:0] wb_insn; output [31:0] simm; output [31:2] branch_addrofs; output [31:0] lsu_addrofs; output [`OR1200_SEL_WIDTH-1:0] sel_a; output [`OR1200_SEL_WIDTH-1:0] sel_b; output [`OR1200_LSUOP_WIDTH-1:0] lsu_op; output [`OR1200_COMPOP_WIDTH-1:0] comp_op; output [`OR1200_MULTICYCLE_WIDTH-1:0] multicycle; output [4:0] cust5_op; output [5:0] cust5_limm; output [15:0] spr_addrimm; input wbforw_valid; input du_hwbkpt; output sig_syscall; output sig_trap; output force_dslot_fetch; output no_more_dslot; output ex_void; output id_macrc_op; output ex_macrc_op; output rfe; output except_illegal; // // Internal wires and regs // reg [`OR1200_BRANCHOP_WIDTH-1:0] pre_branch_op; reg [`OR1200_BRANCHOP_WIDTH-1:0] branch_op; reg [`OR1200_ALUOP_WIDTH-1:0] alu_op; reg [`OR1200_MACOP_WIDTH-1:0] mac_op; reg ex_macrc_op; reg [`OR1200_SHROTOP_WIDTH-1:0] shrot_op; reg [31:0] id_insn; reg [31:0] ex_insn; reg [31:0] wb_insn; reg [`OR1200_REGFILE_ADDR_WIDTH-1:0] rf_addrw; reg [`OR1200_REGFILE_ADDR_WIDTH-1:0] wb_rfaddrw; reg [`OR1200_RFWBOP_WIDTH-1:0] rfwb_op; reg [31:0] lsu_addrofs; reg [`OR1200_SEL_WIDTH-1:0] sel_a; reg [`OR1200_SEL_WIDTH-1:0] sel_b; reg sel_imm; reg [`OR1200_LSUOP_WIDTH-1:0] lsu_op; reg [`OR1200_COMPOP_WIDTH-1:0] comp_op; reg [`OR1200_MULTICYCLE_WIDTH-1:0] multicycle; reg imm_signextend; reg [15:0] spr_addrimm; reg sig_syscall; reg sig_trap; reg except_illegal; wire id_void; // // Register file read addresses // assign rf_addra = if_insn[20:16]; assign rf_addrb = if_insn[15:11]; assign rf_rda = if_insn[31]; assign rf_rdb = if_insn[30]; // // Force fetch of delay slot instruction when jump/branch is preceeded by load/store // instructions // // SIMON // assign force_dslot_fetch = ((|pre_branch_op) & (|lsu_op)); assign force_dslot_fetch = 1'b0; assign no_more_dslot = |branch_op & !id_void & branch_taken | (branch_op == `OR1200_BRANCHOP_RFE); assign id_void = (id_insn[31:26] == `OR1200_OR32_NOP) & id_insn[16]; assign ex_void = (ex_insn[31:26] == `OR1200_OR32_NOP) & ex_insn[16]; // // Sign/Zero extension of immediates // assign simm = (imm_signextend == 1'b1) ? {{id_insn[15]},{id_insn[15]},{id_insn[15]},{id_insn[15]},{id_insn[15]},{id_insn[15]},{id_insn[15]},{id_insn[15]},{id_insn[15]},{id_insn[15]},{id_insn[15]},{id_insn[15]},{id_insn[15]},{id_insn[15]},{id_insn[15]},{id_insn[15]}, id_insn[15:0]} : {{16'b0}, id_insn[15:0]}; // // Sign extension of branch offset // assign branch_addrofs = {{ex_insn[25]},{ex_insn[25]},{ex_insn[25]},{ex_insn[25]},{ex_insn[25]}, ex_insn[25:0]}; // // l.macrc in ID stage // assign id_macrc_op = (id_insn[31:26] == `OR1200_OR32_MOVHI) & id_insn[16]; // // cust5_op, cust5_limm (L immediate) // assign cust5_op = ex_insn[4:0]; assign cust5_limm = ex_insn[10:5]; // // // assign rfe = (pre_branch_op == `OR1200_BRANCHOP_RFE) | (branch_op == `OR1200_BRANCHOP_RFE); // // Generation of sel_a // always @(rf_addrw or id_insn or rfwb_op or wbforw_valid or wb_rfaddrw) if ((id_insn[20:16] == rf_addrw) && rfwb_op[0]) sel_a = `OR1200_SEL_EX_FORW; else if ((id_insn[20:16] == wb_rfaddrw) && wbforw_valid) sel_a = `OR1200_SEL_WB_FORW; else sel_a = `OR1200_SEL_RF; // // Generation of sel_b // always @(rf_addrw or sel_imm or id_insn or rfwb_op or wbforw_valid or wb_rfaddrw) if (sel_imm) sel_b = `OR1200_SEL_IMM; else if ((id_insn[15:11] == rf_addrw) && rfwb_op[0]) sel_b = `OR1200_SEL_EX_FORW; else if ((id_insn[15:11] == wb_rfaddrw) && wbforw_valid) sel_b = `OR1200_SEL_WB_FORW; else sel_b = `OR1200_SEL_RF; // // l.macrc in EX stage // always @(posedge clk ) begin if (rst) ex_macrc_op <= 1'b0; else if (!ex_freeze & id_freeze | flushpipe) ex_macrc_op <= 1'b0; else if (!ex_freeze) ex_macrc_op <= id_macrc_op; end // // Decode of spr_addrimm // always @(posedge clk ) begin if (rst) spr_addrimm <= 16'h0000; else if (!ex_freeze & id_freeze | flushpipe) spr_addrimm <= 16'h0000; else if (!ex_freeze) begin case (id_insn[31:26]) // synopsys parallel_case // l.mfspr `OR1200_OR32_MFSPR: spr_addrimm <= id_insn[15:0]; // l.mtspr default: spr_addrimm <= {id_insn[25:21], id_insn[10:0]}; endcase end end // // Decode of multicycle // always @(id_insn) begin case (id_insn[31:26]) // synopsys parallel_case // l.lwz `OR1200_OR32_LWZ: multicycle = `OR1200_TWO_CYCLES; // l.lbz `OR1200_OR32_LBZ: multicycle = `OR1200_TWO_CYCLES; // l.lbs `OR1200_OR32_LBS: multicycle = `OR1200_TWO_CYCLES; // l.lhz `OR1200_OR32_LHZ: multicycle = `OR1200_TWO_CYCLES; // l.lhs `OR1200_OR32_LHS: multicycle = `OR1200_TWO_CYCLES; // l.sw `OR1200_OR32_SW: multicycle = `OR1200_TWO_CYCLES; // l.sb `OR1200_OR32_SB: multicycle = `OR1200_TWO_CYCLES; // l.sh `OR1200_OR32_SH: multicycle = `OR1200_TWO_CYCLES; // ALU instructions except the one with immediate `OR1200_OR32_ALU: multicycle = id_insn[9:8]; // Single cycle instructions default: begin multicycle = `OR1200_ONE_CYCLE; end endcase end // // Decode of imm_signextend // always @(id_insn) begin case (id_insn[31:26]) // synopsys parallel_case // l.addi `OR1200_OR32_ADDI: imm_signextend = 1'b1; // l.addic `OR1200_OR32_ADDIC: imm_signextend = 1'b1; // l.xori `OR1200_OR32_XORI: imm_signextend = 1'b1; // l.muli `OR1200_OR32_MULI: imm_signextend = 1'b1; // l.maci `OR1200_OR32_MACI: imm_signextend = 1'b1; // SFXX insns with immediate `OR1200_OR32_SFXXI: imm_signextend = 1'b1; // Instructions with no or zero extended immediate default: begin imm_signextend = 1'b0; end endcase end // // LSU addr offset // always @(lsu_op or ex_insn) begin lsu_addrofs[10:0] = ex_insn[10:0]; case(lsu_op) // synopsys parallel_case `OR1200_LSUOP_SB : lsu_addrofs[31:11] = {{{ex_insn[25]}},{{ex_insn[25]}},{{ex_insn[25]}},{{ex_insn[25]}},{{ex_insn[25]}},{{ex_insn[25]}},{{ex_insn[25]}},{{ex_insn[25]}},{{ex_insn[25]}},{{ex_insn[25]}},{{ex_insn[25]}},{{ex_insn[25]}},{{ex_insn[25]}},{{ex_insn[25]}},{{ex_insn[25]}}, ex_insn[25:21]}; `OR1200_LSUOP_SH : lsu_addrofs[31:11] = {{{ex_insn[25]}},{{ex_insn[25]}},{{ex_insn[25]}},{{ex_insn[25]}},{{ex_insn[25]}},{{ex_insn[25]}},{{ex_insn[25]}},{{ex_insn[25]}},{{ex_insn[25]}},{{ex_insn[25]}},{{ex_insn[25]}},{{ex_insn[25]}},{{ex_insn[25]}},{{ex_insn[25]}},{{ex_insn[25]}}, ex_insn[25:21]}; `OR1200_LSUOP_SW : lsu_addrofs[31:11] = {{{ex_insn[25]}},{{ex_insn[25]}},{{ex_insn[25]}},{{ex_insn[25]}},{{ex_insn[25]}},{{ex_insn[25]}},{{ex_insn[25]}},{{ex_insn[25]}},{{ex_insn[25]}},{{ex_insn[25]}},{{ex_insn[25]}},{{ex_insn[25]}},{{ex_insn[25]}},{{ex_insn[25]}},{{ex_insn[25]}}, ex_insn[25:21]}; default : lsu_addrofs[31:11] = {{{ex_insn[15]}},{{ex_insn[15]}},{{ex_insn[15]}},{{ex_insn[15]}},{{ex_insn[15]}},{{ex_insn[15]}},{{ex_insn[15]}},{{ex_insn[15]}},{{ex_insn[15]}},{{ex_insn[15]}},{{ex_insn[15]}},{{ex_insn[15]}},{{ex_insn[15]}},{{ex_insn[15]}},{{ex_insn[15]}},{{ex_insn[15]}}, ex_insn[15:11]}; endcase end // // Register file write address // always @(posedge clk) begin if (rst) rf_addrw <= 5'b00000; else if (!ex_freeze & id_freeze) rf_addrw <= 5'b00000; else if (!ex_freeze) case (pre_branch_op) // synopsys parallel_case `OR1200_BRANCHOP_BAL: rf_addrw <= 5'b01001; // link register r9 `OR1200_BRANCHOP_JR: rf_addrw <= 5'b01001; default: rf_addrw <= id_insn[25:21]; endcase end // // rf_addrw in wb stage (used in forwarding logic) // always @(posedge clk ) begin if (rst) wb_rfaddrw <= 5'b00000; else if (!wb_freeze) wb_rfaddrw <= rf_addrw; end // // Instruction latch in id_insn // always @(posedge clk ) begin if (rst) id_insn <= {`OR1200_OR32_NOP, 26'h0410000}; else if (flushpipe) id_insn <= {`OR1200_OR32_NOP, 26'h0410000}; // id_insn[16] must be 1 else if (!id_freeze) begin id_insn <= if_insn; end end // // Instruction latch in ex_insn // always @(posedge clk ) begin if (rst) ex_insn <= {`OR1200_OR32_NOP, 26'h0410000}; else if (!ex_freeze & id_freeze | flushpipe) ex_insn <= {`OR1200_OR32_NOP, 26'h0410000}; // ex_insn[16] must be 1 else if (!ex_freeze) begin ex_insn <= id_insn; end end // // Instruction latch in wb_insn // always @(posedge clk ) begin if (rst) wb_insn <= {`OR1200_OR32_NOP, 26'h0410000}; else if (flushpipe) wb_insn <= {`OR1200_OR32_NOP, 26'h0410000}; // wb_insn[16] must be 1 else if (!wb_freeze) begin wb_insn <= ex_insn; end end // // Decode of sel_imm // always @(posedge clk ) begin if (rst) sel_imm <= 1'b0; else if (!id_freeze) begin case (if_insn[31:26]) // synopsys parallel_case // j.jalr `OR1200_OR32_JALR: sel_imm <= 1'b0; // l.jr `OR1200_OR32_JR: sel_imm <= 1'b0; // l.rfe `OR1200_OR32_RFE: sel_imm <= 1'b0; // l.mfspr `OR1200_OR32_MFSPR: sel_imm <= 1'b0; // l.mtspr `OR1200_OR32_MTSPR: sel_imm <= 1'b0; // l.sys, l.brk and all three sync insns `OR1200_OR32_XSYNC: sel_imm <= 1'b0; // l.mac/l.msb `OR1200_OR32_MACMSB: sel_imm <= 1'b0; // l.sw `OR1200_OR32_SW: sel_imm <= 1'b0; // l.sb `OR1200_OR32_SB: sel_imm <= 1'b0; // l.sh `OR1200_OR32_SH: sel_imm <= 1'b0; // ALU instructions except the one with immediate `OR1200_OR32_ALU: sel_imm <= 1'b0; // SFXX instructions `OR1200_OR32_SFXX: sel_imm <= 1'b0; // l.cust5 instructions `OR1200_OR32_CUST5: sel_imm <= 1'b0; // l.nop `OR1200_OR32_NOP: sel_imm <= 1'b0; // All instructions with immediates default: begin sel_imm <= 1'b1; end endcase end end // // Decode of except_illegal // always @(posedge clk ) begin if (rst) except_illegal <= 1'b0; else if (!ex_freeze & id_freeze | flushpipe) except_illegal <= 1'b0; else if (!ex_freeze) begin except_illegal <= 1'b1; end end // // Decode of alu_op // always @(posedge clk ) begin if (rst) alu_op <= `OR1200_ALUOP_NOP; else if (!ex_freeze & id_freeze | flushpipe) alu_op <= `OR1200_ALUOP_NOP; else if (!ex_freeze) begin case (id_insn[31:26]) // synopsys parallel_case // l.j `OR1200_OR32_J: alu_op <= `OR1200_ALUOP_IMM; // j.jal `OR1200_OR32_JAL: alu_op <= `OR1200_ALUOP_IMM; // l.bnf `OR1200_OR32_BNF: alu_op <= `OR1200_ALUOP_NOP; // l.bf `OR1200_OR32_BF: alu_op <= `OR1200_ALUOP_NOP; // l.movhi `OR1200_OR32_MOVHI: alu_op <= `OR1200_ALUOP_MOVHI; // l.mfspr `OR1200_OR32_MFSPR: alu_op <= `OR1200_ALUOP_MFSR; // l.mtspr `OR1200_OR32_MTSPR: alu_op <= `OR1200_ALUOP_MTSR; // l.addi `OR1200_OR32_ADDI: alu_op <= `OR1200_ALUOP_ADD; // l.addic `OR1200_OR32_ADDIC: alu_op <= `OR1200_ALUOP_ADDC; // l.andi `OR1200_OR32_ANDI: alu_op <= `OR1200_ALUOP_AND; // l.ori `OR1200_OR32_ORI: alu_op <= `OR1200_ALUOP_OR; // l.xori `OR1200_OR32_XORI: alu_op <= `OR1200_ALUOP_XOR; // l.muli `OR1200_OR32_MULI: alu_op <= `OR1200_ALUOP_MUL; // Shift and rotate insns with immediate `OR1200_OR32_SH_ROTI: alu_op <= `OR1200_ALUOP_SHROT; // SFXX insns with immediate `OR1200_OR32_SFXXI: alu_op <= `OR1200_ALUOP_COMP; // ALU instructions except the one with immediate `OR1200_OR32_ALU: alu_op <= id_insn[3:0]; // SFXX instructions `OR1200_OR32_SFXX: alu_op <= `OR1200_ALUOP_COMP; // l.cust5 instructions `OR1200_OR32_CUST5: alu_op <= `OR1200_ALUOP_CUST5; // Default default: begin alu_op <= `OR1200_ALUOP_NOP; end endcase end end // // Decode of mac_op always @(posedge clk ) begin if (rst) mac_op <= `OR1200_MACOP_NOP; else if (!ex_freeze & id_freeze | flushpipe) mac_op <= `OR1200_MACOP_NOP; else if (!ex_freeze) case (id_insn[31:26]) // synopsys parallel_case // l.maci `OR1200_OR32_MACI: mac_op <= `OR1200_MACOP_MAC; // l.nop `OR1200_OR32_MACMSB: mac_op <= id_insn[1:0]; // Illegal and OR1200 unsupported instructions default: begin mac_op <= `OR1200_MACOP_NOP; end endcase else mac_op <= `OR1200_MACOP_NOP; end // // Decode of shrot_op // always @(posedge clk ) begin if (rst) shrot_op <= `OR1200_SHROTOP_NOP; else if (!ex_freeze & id_freeze | flushpipe) shrot_op <= `OR1200_SHROTOP_NOP; else if (!ex_freeze) begin shrot_op <= id_insn[7:6]; end end // // Decode of rfwb_op // always @(posedge clk ) begin if (rst) rfwb_op <= `OR1200_RFWBOP_NOP; else if (!ex_freeze & id_freeze | flushpipe) rfwb_op <= `OR1200_RFWBOP_NOP; else if (!ex_freeze) begin case (id_insn[31:26]) // synopsys parallel_case // j.jal `OR1200_OR32_JAL: rfwb_op <= `OR1200_RFWBOP_LR; // j.jalr `OR1200_OR32_JALR: rfwb_op <= `OR1200_RFWBOP_LR; // l.movhi `OR1200_OR32_MOVHI: rfwb_op <= `OR1200_RFWBOP_ALU; // l.mfspr `OR1200_OR32_MFSPR: rfwb_op <= `OR1200_RFWBOP_SPRS; // l.lwz `OR1200_OR32_LWZ: rfwb_op <= `OR1200_RFWBOP_LSU; // l.lbz `OR1200_OR32_LBZ: rfwb_op <= `OR1200_RFWBOP_LSU; // l.lbs `OR1200_OR32_LBS: rfwb_op <= `OR1200_RFWBOP_LSU; // l.lhz `OR1200_OR32_LHZ: rfwb_op <= `OR1200_RFWBOP_LSU; // l.lhs `OR1200_OR32_LHS: rfwb_op <= `OR1200_RFWBOP_LSU; // l.addi `OR1200_OR32_ADDI: rfwb_op <= `OR1200_RFWBOP_ALU; // l.addic `OR1200_OR32_ADDIC: rfwb_op <= `OR1200_RFWBOP_ALU; // l.andi `OR1200_OR32_ANDI: rfwb_op <= `OR1200_RFWBOP_ALU; // l.ori `OR1200_OR32_ORI: rfwb_op <= `OR1200_RFWBOP_ALU; // l.xori `OR1200_OR32_XORI: rfwb_op <= `OR1200_RFWBOP_ALU; // l.muli `OR1200_OR32_MULI: rfwb_op <= `OR1200_RFWBOP_ALU; // Shift and rotate insns with immediate `OR1200_OR32_SH_ROTI: rfwb_op <= `OR1200_RFWBOP_ALU; // ALU instructions except the one with immediate `OR1200_OR32_ALU: rfwb_op <= `OR1200_RFWBOP_ALU; // l.cust5 instructions `OR1200_OR32_CUST5: rfwb_op <= `OR1200_RFWBOP_ALU; // Instructions w/o register-file write-back default: begin rfwb_op <= `OR1200_RFWBOP_NOP; end endcase end end // // Decode of pre_branch_op // always @(posedge clk ) begin if (rst) pre_branch_op <= `OR1200_BRANCHOP_NOP; else if (flushpipe) pre_branch_op <= `OR1200_BRANCHOP_NOP; else if (!id_freeze) begin case (if_insn[31:26]) // synopsys parallel_case // l.j `OR1200_OR32_J: pre_branch_op <= `OR1200_BRANCHOP_BAL; // j.jal `OR1200_OR32_JAL: pre_branch_op <= `OR1200_BRANCHOP_BAL; // j.jalr `OR1200_OR32_JALR: pre_branch_op <= `OR1200_BRANCHOP_JR; // l.jr `OR1200_OR32_JR: pre_branch_op <= `OR1200_BRANCHOP_JR; // l.bnf `OR1200_OR32_BNF: pre_branch_op <= `OR1200_BRANCHOP_BNF; // l.bf `OR1200_OR32_BF: pre_branch_op <= `OR1200_BRANCHOP_BF; // l.rfe `OR1200_OR32_RFE: pre_branch_op <= `OR1200_BRANCHOP_RFE; // Non branch instructions default: begin pre_branch_op <= `OR1200_BRANCHOP_NOP; end endcase end end // // Generation of branch_op // always @(posedge clk ) if (rst) branch_op <= `OR1200_BRANCHOP_NOP; else if (!ex_freeze & id_freeze | flushpipe) branch_op <= `OR1200_BRANCHOP_NOP; else if (!ex_freeze) branch_op <= pre_branch_op; // // Decode of lsu_op // always @(posedge clk ) begin if (rst) lsu_op <= `OR1200_LSUOP_NOP; else if (!ex_freeze & id_freeze | flushpipe) lsu_op <= `OR1200_LSUOP_NOP; else if (!ex_freeze) begin case (id_insn[31:26]) // synopsys parallel_case // l.lwz `OR1200_OR32_LWZ: lsu_op <= `OR1200_LSUOP_LWZ; // l.lbz `OR1200_OR32_LBZ: lsu_op <= `OR1200_LSUOP_LBZ; // l.lbs `OR1200_OR32_LBS: lsu_op <= `OR1200_LSUOP_LBS; // l.lhz `OR1200_OR32_LHZ: lsu_op <= `OR1200_LSUOP_LHZ; // l.lhs `OR1200_OR32_LHS: lsu_op <= `OR1200_LSUOP_LHS; // l.sw `OR1200_OR32_SW: lsu_op <= `OR1200_LSUOP_SW; // l.sb `OR1200_OR32_SB: lsu_op <= `OR1200_LSUOP_SB; // l.sh `OR1200_OR32_SH: lsu_op <= `OR1200_LSUOP_SH; // Non load/store instructions default: begin lsu_op <= `OR1200_LSUOP_NOP; end endcase end end // // Decode of comp_op // always @(posedge clk ) begin if (rst) begin comp_op <= 4'b0000; end else if (!ex_freeze & id_freeze | flushpipe) comp_op <= 4'b0000; else if (!ex_freeze) comp_op <= id_insn[24:21]; end // // Decode of l.sys // always @(posedge clk ) begin if (rst) sig_syscall <= 1'b0; else if (!ex_freeze & id_freeze | flushpipe) sig_syscall <= 1'b0; else if (!ex_freeze) begin sig_syscall <= (id_insn[31:23] == {`OR1200_OR32_XSYNC, 3'b000}); end end // // Decode of l.trap // always @(posedge clk ) begin if (rst) sig_trap <= 1'b0; else if (!ex_freeze & id_freeze | flushpipe) sig_trap <= 1'b0; else if (!ex_freeze) begin sig_trap <= (id_insn[31:23] == {`OR1200_OR32_XSYNC, 3'b010}) | du_hwbkpt; end end endmodule module or1200_rf( // Clock and reset clk, rst, // Write i/f supv, wb_freeze, addrw, dataw,id_freeze, we, flushpipe, // Read i/f addra, rda, dataa, addrb,rdb, datab, // Debug spr_cs, spr_write, spr_addr, spr_dat_i, spr_dat_o ); //parameter aw = `OR1200_OPERAND_WIDTH; //parameter dw= `OR1200_REGFILE_ADDR_WIDTH; // // I/O // // // Clock and reset // input clk; input rst; // // Write i/f // input supv; input wb_freeze; input [`OR1200_REGFILE_ADDR_WIDTH-1:0] addrw; input [`OR1200_OPERAND_WIDTH-1:0] dataw; input we; input flushpipe; // // Read i/f // input id_freeze; input [`OR1200_REGFILE_ADDR_WIDTH-1:0] addra; input [`OR1200_REGFILE_ADDR_WIDTH-1:0] addrb; output [`OR1200_OPERAND_WIDTH-1:0] dataa; output [`OR1200_OPERAND_WIDTH-1:0] datab; input rda; input rdb; // // SPR access for debugging purposes // input spr_cs; input spr_write; input [31:0] spr_addr; input [31:0] spr_dat_i; output [31:0] spr_dat_o; // // Internal wires and regs // wire [`OR1200_OPERAND_WIDTH-1:0] from_rfa; wire [`OR1200_OPERAND_WIDTH-1:0] from_rfb; reg [`OR1200_OPERAND_WIDTH:0] dataa_saved; reg [`OR1200_OPERAND_WIDTH:0] datab_saved; wire [`OR1200_REGFILE_ADDR_WIDTH-1:0] rf_addra; wire [`OR1200_REGFILE_ADDR_WIDTH-1:0] rf_addrw; wire [`OR1200_OPERAND_WIDTH-1:0] rf_dataw; wire rf_we; wire spr_valid; wire rf_ena; wire rf_enb; reg rf_we_allow; // // SPR access is valid when spr_cs is asserted and // SPR address matches GPR addresses // assign spr_valid = spr_cs & (spr_addr[10:5] == `OR1200_SPR_RF); // // SPR data output is always from RF A // assign spr_dat_o = from_rfa; // // Operand A comes from RF or from saved A register // assign dataa = (dataa_saved[32]) ? dataa_saved[31:0] : from_rfa; // // Operand B comes from RF or from saved B register // assign datab = (datab_saved[32]) ? datab_saved[31:0] : from_rfb; // // RF A read address is either from SPRS or normal from CPU control // assign rf_addra = (spr_valid & !spr_write) ? spr_addr[4:0] : addra; // // RF write address is either from SPRS or normal from CPU control // assign rf_addrw = (spr_valid & spr_write) ? spr_addr[4:0] : addrw; // // RF write data is either from SPRS or normal from CPU datapath // assign rf_dataw = (spr_valid & spr_write) ? spr_dat_i : dataw; // // RF write enable is either from SPRS or normal from CPU control // always @(posedge clk) if (rst) rf_we_allow <= 1'b1; else if (~wb_freeze) rf_we_allow <= ~flushpipe; assign rf_we = ((spr_valid & spr_write) | (we & ~wb_freeze)) & rf_we_allow & (supv | (|rf_addrw)); // // CS RF A asserted when instruction reads operand A and ID stage // is not stalled // assign rf_ena = rda & ~id_freeze | spr_valid; // probably works with fixed binutils // assign rf_ena = 1'b1; // does not work with single-stepping //assign rf_ena = ~id_freeze | spr_valid; // works with broken binutils // // CS RF B asserted when instruction reads operand B and ID stage // is not stalled // assign rf_enb = rdb & ~id_freeze | spr_valid; // assign rf_enb = 1'b1; //assign rf_enb = ~id_freeze | spr_valid; // works with broken binutils // // Stores operand from RF_A into temp reg when pipeline is frozen // always @(posedge clk ) if (rst) begin dataa_saved <=33'b000000000000000000000000000000000; end else if (id_freeze & !dataa_saved[32]) begin dataa_saved <= {1'b1, from_rfa}; end else if (!id_freeze) dataa_saved <=33'b000000000000000000000000000000000; // // Stores operand from RF_B into temp reg when pipeline is frozen // always @(posedge clk) if (rst) begin datab_saved <= 33'b000000000000000000000000000000000; end else if (id_freeze & !datab_saved[32]) begin datab_saved <= {1'b1, from_rfb}; end else if (!id_freeze) datab_saved <= 33'b000000000000000000000000000000000; // Black-box memory instead of the or1200 memory implementation wire const_one; wire const_zero; assign const_one = 1'b1; assign const_zero = 1'b0; wire [31:0] const_zero_data; assign const_zero_data = 32'b00000000000000000000000000000000; wire [31:0] dont_care_out; wire [31:0] dont_care_out2; dual_port_ram rf_a( .clk (clk), .we1(const_zero), .we2(rf_we), .data1(const_zero_data), .data2(rf_dataw), .out1(from_rfa), .out2 (dont_care_out), .addr1(rf_addra), .addr2(rf_addrw)); // // Instantiation of register file two-port RAM A // /* or1200_tpram_32x32 rf_a( // Port A .clk_a(clk), .rst_a(rst), .ce_a(rf_ena), .we_a(1'b0), .oe_a(1'b1), .addr_a(rf_addra), .di_a(32'h00000000), .do_a(from_rfa), // Port B .clk_b(clk), .rst_b(rst), .ce_b(rf_we), .we_b(rf_we), .oe_b(1'b0), .addr_b(rf_addrw), .di_b(rf_dataw), .do_b() ); */ // // Instantiation of register file two-port RAM B // dual_port_ram rf_b( .clk (clk), .we1(const_zero), .we2(rf_we), .data1(const_zero_data), .data2(rf_dataw), .out1(from_rfb), .out2 (dont_care_out2), .addr1(addrb), .addr2(rf_addrw)); /* or1200_tpram_32x32 rf_b( // Port A .clk_a(clk), .rst_a(rst), .ce_a(rf_enb), .we_a(1'b0), .oe_a(1'b1), .addr_a(addrb), .di_a(32'h00000000), .do_a(from_rfb), // Port B .clk_b(clk), .rst_b(rst), .ce_b(rf_we), .we_b(rf_we), .oe_b(1'b0), .addr_b(rf_addrw), .di_b(rf_dataw), .do_b() ); */ wire unused; assign unused = |spr_addr; endmodule module or1200_operandmuxes( // Clock and reset clk, rst, // Internal i/f id_freeze, ex_freeze, rf_dataa, rf_datab, ex_forw, wb_forw, simm, sel_a, sel_b, operand_a, operand_b, muxed_b ); //parameter width = `OR1200_OPERAND_WIDTH; // // I/O // input clk; input rst; input id_freeze; input ex_freeze; input [`OR1200_OPERAND_WIDTH-1:0] rf_dataa; input [`OR1200_OPERAND_WIDTH-1:0] rf_datab; input [`OR1200_OPERAND_WIDTH-1:0] ex_forw; input [`OR1200_OPERAND_WIDTH-1:0] wb_forw; input [`OR1200_OPERAND_WIDTH-1:0] simm; input [`OR1200_SEL_WIDTH-1:0] sel_a; input [`OR1200_SEL_WIDTH-1:0] sel_b; output [`OR1200_OPERAND_WIDTH-1:0] operand_a; output [`OR1200_OPERAND_WIDTH-1:0] operand_b; output [`OR1200_OPERAND_WIDTH-1:0] muxed_b; // // Internal wires and regs // reg [`OR1200_OPERAND_WIDTH-1:0] operand_a; reg [`OR1200_OPERAND_WIDTH-1:0] operand_b; reg [`OR1200_OPERAND_WIDTH-1:0] muxed_a; reg [`OR1200_OPERAND_WIDTH-1:0] muxed_b; reg saved_a; reg saved_b; // // Operand A register // always @(posedge clk ) begin if (rst) begin operand_a <= 32'b0000000000000000000000000000; saved_a <= 1'b0; end else if (!ex_freeze && id_freeze && !saved_a) begin operand_a <= muxed_a; saved_a <= 1'b1; end else if (!ex_freeze && !saved_a) begin operand_a <= muxed_a; end else if (!ex_freeze && !id_freeze) saved_a <= 1'b0; end // // Operand B register // always @(posedge clk ) begin if (rst) begin operand_b <= 32'b0000000000000000000000000000; saved_b <= 1'b0; end else if (!ex_freeze && id_freeze && !saved_b) begin operand_b <= muxed_b; saved_b <= 1'b1; end else if (!ex_freeze && !saved_b) begin operand_b <= muxed_b; end else if (!ex_freeze && !id_freeze) saved_b <= 1'b0; end // // Forwarding logic for operand A register // always @(ex_forw or wb_forw or rf_dataa or sel_a) begin case (sel_a) `OR1200_SEL_EX_FORW: muxed_a = ex_forw; `OR1200_SEL_WB_FORW: muxed_a = wb_forw; default: muxed_a = rf_dataa; endcase end // // Forwarding logic for operand B register // always @(simm or ex_forw or wb_forw or rf_datab or sel_b) begin case (sel_b) // synopsys parallel_case `OR1200_SEL_IMM: muxed_b = simm; `OR1200_SEL_EX_FORW: muxed_b = ex_forw; `OR1200_SEL_WB_FORW: muxed_b = wb_forw; default: muxed_b = rf_datab; endcase end endmodule module or1200_alu( a, b, mult_mac_result, macrc_op, alu_op, shrot_op, comp_op, cust5_op, cust5_limm, result, flagforw, flag_we, cyforw, cy_we, flag,k_carry ); // // I/O // input [32-1:0] a; input [32-1:0] b; input [32-1:0] mult_mac_result; input macrc_op; input [`OR1200_ALUOP_WIDTH-1:0] alu_op; input [2-1:0] shrot_op; input [4-1:0] comp_op; input [4:0] cust5_op; input [5:0] cust5_limm; output [32-1:0] result; output flagforw; output flag_we; output cyforw; output cy_we; input k_carry; input flag; // // Internal wires and regs // reg [32-1:0] result; reg [32-1:0] shifted_rotated; reg [32-1:0] result_cust5; reg flagforw; reg flagcomp; reg flag_we; reg cy_we; wire [32-1:0] comp_a; wire [32-1:0] comp_b; wire a_eq_b; wire a_lt_b; wire [32-1:0] result_sum; wire [32-1:0] result_csum; wire cy_csum; wire [32-1:0] result_and; wire cy_sum; reg cyforw; // // Combinatorial logic // assign comp_a [31:3]= a[31] ^ comp_op[3]; assign comp_a [2:0] = a[30:0]; assign comp_b [31:3] = b[31] ^ comp_op[3] ; assign comp_b [2:0] = b[32-2:0]; assign a_eq_b = (comp_a == comp_b); assign a_lt_b = (comp_a < comp_b); assign cy_sum= a + b; assign result_sum = a+b; assign cy_csum =a + b + {32'b00000000000000000000000000000000, k_carry}; assign result_csum = a + b + {32'b00000000000000000000000000000000, k_carry}; assign result_and = a & b; // Central part of the ALU // always @(alu_op or a or b or result_sum or result_and or macrc_op or shifted_rotated or mult_mac_result) begin case (alu_op) // synopsys parallel_case 4'b1111: begin result = a[0] ? 1 : a[1] ? 2 : a[2] ? 3 : a[3] ? 4 : a[4] ? 5 : a[5] ? 6 : a[6] ? 7 : a[7] ? 8 : a[8] ? 9 : a[9] ? 10 : a[10] ? 11 : a[11] ? 12 : a[12] ? 13 : a[13] ? 14 : a[14] ? 15 : a[15] ? 16 : a[16] ? 17 : a[17] ? 18 : a[18] ? 19 : a[19] ? 20 : a[20] ? 21 : a[21] ? 22 : a[22] ? 23 : a[23] ? 24 : a[24] ? 25 : a[25] ? 26 : a[26] ? 27 : a[27] ? 28 : a[28] ? 29 : a[29] ? 30 : a[30] ? 31 : a[31] ? 32 : 0; end `OR1200_ALUOP_CUST5 : begin result = result_cust5; end `OR1200_ALUOP_SHROT : begin result = shifted_rotated; end `OR1200_ALUOP_ADD : begin result = result_sum; end `OR1200_ALUOP_ADDC : begin result = result_csum; end `OR1200_ALUOP_SUB : begin result = a - b; end `OR1200_ALUOP_XOR : begin result = a ^ b; end `OR1200_ALUOP_OR : begin result = a | b; end `OR1200_ALUOP_IMM : begin result = b; end `OR1200_ALUOP_MOVHI : begin if (macrc_op) begin result = mult_mac_result; end else begin result = b << 16; end end `OR1200_ALUOP_MUL : begin result = mult_mac_result; end 4'b1110: begin result = flag ? a : b; end default: begin result=result_and; end endcase end // // l.cust5 custom instructions // // Examples for move byte, set bit and clear bit // always @(cust5_op or cust5_limm or a or b) begin case (cust5_op) // synopsys parallel_case 5'h1 : begin case (cust5_limm[1:0]) 2'h0: result_cust5 = {a[31:8], b[7:0]}; 2'h1: result_cust5 = {a[31:16], b[7:0], a[7:0]}; 2'h2: result_cust5 = {a[31:24], b[7:0], a[15:0]}; 2'h3: result_cust5 = {b[7:0], a[23:0]}; endcase end 5'h2 : result_cust5 = a | (1 << 4); 5'h3 : result_cust5 = a & (32'b11111111111111111111111111111111^ (cust5_limm)); // // *** Put here new l.cust5 custom instructions *** // default: begin result_cust5 = a; end endcase end // // Generate flag and flag write enable // always @(alu_op or result_sum or result_and or flagcomp) begin case (alu_op) // synopsys parallel_case `OR1200_ALUOP_ADD : begin flagforw = (result_sum == 32'b00000000000000000000000000000000); flag_we = 1'b1; end `OR1200_ALUOP_ADDC : begin flagforw = (result_csum == 32'b00000000000000000000000000000000); flag_we = 1'b1; end `OR1200_ALUOP_AND: begin flagforw = (result_and == 32'b00000000000000000000000000000000); flag_we = 1'b1; end `OR1200_ALUOP_COMP: begin flagforw = flagcomp; flag_we = 1'b1; end default: begin flagforw = 1'b0; flag_we = 1'b0; end endcase end // // Generate SR[CY] write enable // always @(alu_op or cy_sum ) begin case (alu_op) // synopsys parallel_case `OR1200_ALUOP_ADD : begin cyforw = cy_sum; cy_we = 1'b1; end `OR1200_ALUOP_ADDC: begin cyforw = cy_csum; cy_we = 1'b1; end default: begin cyforw = 1'b0; cy_we = 1'b0; end endcase end // // Shifts and rotation // always @(shrot_op or a or b) begin case (shrot_op) // synopsys parallel_case 2'b00 : shifted_rotated = (a << 2); `OR1200_SHROTOP_SRL : shifted_rotated = (a >> 2); `OR1200_SHROTOP_ROR : shifted_rotated = (a << 1'b1); default: shifted_rotated = (a << 1); endcase end // // First type of compare implementation // always @(comp_op or a_eq_b or a_lt_b) begin case(comp_op[2:0]) // synopsys parallel_case `OR1200_COP_SFEQ: flagcomp = a_eq_b; `OR1200_COP_SFNE: flagcomp = ~a_eq_b; `OR1200_COP_SFGT: flagcomp = ~(a_eq_b | a_lt_b); `OR1200_COP_SFGE: flagcomp = ~a_lt_b; `OR1200_COP_SFLT: flagcomp = a_lt_b; `OR1200_COP_SFLE: flagcomp = a_eq_b | a_lt_b; default: flagcomp = 1'b0; endcase end // endmodule module or1200_mult_mac( // Clock and reset clk, rst, // Multiplier/MAC interface ex_freeze, id_macrc_op, macrc_op, a, b, mac_op, alu_op, result, mac_stall_r, // SPR interface spr_cs, spr_write, spr_addr, spr_dat_i, spr_dat_o ); //parameter width = `OR1200_OPERAND_WIDTH; // // I/O // // // Clock and reset // input clk; input rst; // // Multiplier/MAC interface // input ex_freeze; input id_macrc_op; input macrc_op; input [`OR1200_OPERAND_WIDTH-1:0] a; input [`OR1200_OPERAND_WIDTH-1:0] b; input [`OR1200_MACOP_WIDTH-1:0] mac_op; input [`OR1200_ALUOP_WIDTH-1:0] alu_op; output [`OR1200_OPERAND_WIDTH-1:0] result; output mac_stall_r; // // SPR interface // input spr_cs; input spr_write; input [31:0] spr_addr; input [31:0] spr_dat_i; output [31:0] spr_dat_o; // // Internal wires and regs // reg [`OR1200_OPERAND_WIDTH-1:0] result; reg [2*`OR1200_OPERAND_WIDTH-1:0] mul_prod_r; wire [2*`OR1200_OPERAND_WIDTH-1:0] mul_prod; wire [`OR1200_MACOP_WIDTH-1:0] mac_op; reg [`OR1200_MACOP_WIDTH-1:0] mac_op_r1; reg [`OR1200_MACOP_WIDTH-1:0] mac_op_r2; reg [`OR1200_MACOP_WIDTH-1:0] mac_op_r3; reg mac_stall_r; reg [2*`OR1200_OPERAND_WIDTH-1:0] mac_r; wire [`OR1200_OPERAND_WIDTH-1:0] x; wire [`OR1200_OPERAND_WIDTH-1:0] y; wire spr_maclo_we; wire spr_machi_we; wire alu_op_div_divu; wire alu_op_div; reg div_free; wire [`OR1200_OPERAND_WIDTH-1:0] div_tmp; reg [5:0] div_cntr; // // Combinatorial logic // assign spr_maclo_we = spr_cs & spr_write & spr_addr[`OR1200_MAC_ADDR]; assign spr_machi_we = spr_cs & spr_write & !spr_addr[`OR1200_MAC_ADDR]; assign spr_dat_o = spr_addr[`OR1200_MAC_ADDR] ? mac_r[31:0] : mac_r[63:32]; assign x = (alu_op_div & a[31]) ? ~a + 1'b1 : alu_op_div_divu | (alu_op == `OR1200_ALUOP_MUL) | (|mac_op) ? a : 32'h00000000; assign y = (alu_op_div & b[31]) ? ~b + 1'b1 : alu_op_div_divu | (alu_op == `OR1200_ALUOP_MUL) | (|mac_op) ? b : 32'h00000000; assign alu_op_div = (alu_op == `OR1200_ALUOP_DIV); assign alu_op_div_divu = alu_op_div | (alu_op == `OR1200_ALUOP_DIVU); assign div_tmp = mul_prod_r[63:32] - y; // // Select result of current ALU operation to be forwarded // to next instruction and to WB stage // always @(alu_op or mul_prod_r or mac_r or a or b) case(alu_op) `OR1200_ALUOP_DIV: result = a[31] ^ b[31] ? ~mul_prod_r[31:0] + 1'b1 : mul_prod_r[31:0]; `OR1200_ALUOP_DIVU: begin result = mul_prod_r[31:0]; end `OR1200_ALUOP_MUL: begin result = mul_prod_r[31:0]; end default: result = mac_r[31:0]; endcase // // Instantiation of the multiplier // // doing an implicit multiply here assign mul_prod = x * y; /* or1200_gmultp2_32x32 or1200_gmultp2_32x32( .X(x), .Y(y), .RST(rst), .CLK(clk), .P(mul_prod) ); */ // // Registered output from the multiplier and // an optional divider // always @(posedge clk) if (rst) begin mul_prod_r <= 64'h0000000000000000; div_free <= 1'b1; div_cntr <= 6'b000000; end else if (|div_cntr) begin if (div_tmp[31]) mul_prod_r <= {mul_prod_r[62:0], 1'b0}; else mul_prod_r <= {div_tmp[30:0], mul_prod_r[31:0], 1'b1}; div_cntr <= div_cntr - 1'b1; end else if (alu_op_div_divu && div_free) begin mul_prod_r <= {31'b0000000000000000000000000000000, x[31:0], 1'b0}; div_cntr <= 6'b100000; div_free <= 1'b0; end else if (div_free | !ex_freeze) begin mul_prod_r <= mul_prod[63:0]; div_free <= 1'b1; end // Propagation of l.mac opcode // always @(posedge clk) if (rst) mac_op_r1 <= 2'b00; else mac_op_r1 <= mac_op; // // Propagation of l.mac opcode // always @(posedge clk) if (rst) mac_op_r2 <= 2'b00; else mac_op_r2 <= mac_op_r1; // // Propagation of l.mac opcode // always @(posedge clk ) if (rst) mac_op_r3 <= 2'b00; else mac_op_r3 <= mac_op_r2; // // Implementation of MAC // always @(posedge clk) if (rst) mac_r <= 64'h0000000000000000; else if (spr_maclo_we) mac_r[31:0] <= spr_dat_i; else if (spr_machi_we) mac_r[63:32] <= spr_dat_i; else if (mac_op_r3 == `OR1200_MACOP_MAC) mac_r <= mac_r + mul_prod_r; else if (mac_op_r3 == `OR1200_MACOP_MSB) mac_r <= mac_r - mul_prod_r; else if (macrc_op & !ex_freeze) mac_r <= 64'h0000000000000000; // // Stall CPU if l.macrc is in ID and MAC still has to process l.mac instructions // in EX stage (e.g. inside multiplier) // This stall signal is also used by the divider. // wire unused; assign unused = |spr_addr; always @( posedge clk) if (rst) mac_stall_r <= 1'b0; else mac_stall_r <= (|mac_op | (|mac_op_r1) | (|mac_op_r2)) & id_macrc_op | (|div_cntr) ; endmodule module or1200_sprs( // Clk & Rst clk, rst, // Internal CPU interface addrbase, addrofs, dat_i, alu_op, flagforw, flag_we, flag, cyforw, cy_we, carry, to_wbmux, du_addr, du_dat_du, du_read, du_write, du_dat_cpu, spr_addr,spr_dat_pic, spr_dat_tt, spr_dat_pm, spr_dat_cfgr, spr_dat_rf, spr_dat_npc, spr_dat_ppc, spr_dat_mac, spr_dat_dmmu, spr_dat_immu, spr_dat_du, spr_dat_o, spr_cs, spr_we, epcr_we, eear_we,esr_we, pc_we,epcr, eear, esr, except_started, sr_we, to_sr, sr,branch_op ); //parameter width = `OR1200_OPERAND_WIDTH; // // I/O Ports // // // Internal CPU interface // input clk; // Clock input rst; // Reset input flagforw; // From ALU input flag_we; // From ALU output flag; // SR[F] input cyforw; // From ALU input cy_we; // From ALU output carry; // SR[CY] input [`OR1200_OPERAND_WIDTH-1:0] addrbase; // SPR base address input [15:0] addrofs; // SPR offset input [`OR1200_OPERAND_WIDTH-1:0] dat_i; // SPR write data input [`OR1200_ALUOP_WIDTH-1:0] alu_op; // ALU operation input [`OR1200_BRANCHOP_WIDTH-1:0] branch_op; // Branch operation input [`OR1200_OPERAND_WIDTH-1:0] epcr; // EPCR0 input [`OR1200_OPERAND_WIDTH-1:0] eear; // EEAR0 input [`OR1200_SR_WIDTH-1:0] esr; // ESR0 input except_started; // Exception was started output [`OR1200_OPERAND_WIDTH-1:0] to_wbmux; // For l.mfspr output epcr_we; // EPCR0 write enable output eear_we; // EEAR0 write enable output esr_we; // ESR0 write enable output pc_we; // PC write enable output sr_we; // Write enable SR output [`OR1200_SR_WIDTH-1:0] to_sr; // Data to SR output [`OR1200_SR_WIDTH-1:0] sr; // SR input [31:0] spr_dat_cfgr; // Data from CFGR input [31:0] spr_dat_rf; // Data from RF input [31:0] spr_dat_npc; // Data from NPC input [31:0] spr_dat_ppc; // Data from PPC input [31:0] spr_dat_mac; // Data from MAC // // To/from other RISC units // input [31:0] spr_dat_pic; // Data from PIC input [31:0] spr_dat_tt; // Data from TT input [31:0] spr_dat_pm; // Data from PM input [31:0] spr_dat_dmmu; // Data from DMMU input [31:0] spr_dat_immu; // Data from IMMU input [31:0] spr_dat_du; // Data from DU output [31:0] spr_addr; // SPR Address output [31:0] spr_dat_o; // Data to unit output [31:0] spr_cs; // Unit select output spr_we; // SPR write enable // // To/from Debug Unit // input [`OR1200_OPERAND_WIDTH-1:0] du_addr; // Address input [`OR1200_OPERAND_WIDTH-1:0] du_dat_du; // Data from DU to SPRS input du_read; // Read qualifier input du_write; // Write qualifier output [`OR1200_OPERAND_WIDTH-1:0] du_dat_cpu; // Data from SPRS to DU // // Internal regs & wires // reg [`OR1200_SR_WIDTH-1:0] sr; // SR reg write_spr; // Write SPR reg read_spr; // Read SPR reg [`OR1200_OPERAND_WIDTH-1:0] to_wbmux; // For l.mfspr wire cfgr_sel; // Select for cfg regs wire rf_sel; // Select for RF wire npc_sel; // Select for NPC wire ppc_sel; // Select for PPC wire sr_sel; // Select for SR wire epcr_sel; // Select for EPCR0 wire eear_sel; // Select for EEAR0 wire esr_sel; // Select for ESR0 wire [31:0] sys_data; // Read data from system SPRs wire du_access; // Debug unit access wire [`OR1200_ALUOP_WIDTH-1:0] sprs_op; // ALU operation reg [31:0] unqualified_cs; // Unqualified chip selects // // Decide if it is debug unit access // assign du_access = du_read | du_write; // // Generate sprs opcode // assign sprs_op = du_write ? `OR1200_ALUOP_MTSR : du_read ? `OR1200_ALUOP_MFSR : alu_op; // // Generate SPR address from base address and offset // OR from debug unit address // assign spr_addr = du_access ? du_addr : addrbase | {16'h0000, addrofs}; // // SPR is written by debug unit or by l.mtspr // assign spr_dat_o = du_write ? du_dat_du : dat_i; // // debug unit data input: // - write into debug unit SPRs by debug unit itself // - read of SPRS by debug unit // - write into debug unit SPRs by l.mtspr // assign du_dat_cpu = du_write ? du_dat_du : du_read ? to_wbmux : dat_i; // // Write into SPRs when l.mtspr // assign spr_we = du_write | write_spr; // // Qualify chip selects // assign spr_cs = unqualified_cs & {{read_spr | write_spr},{read_spr | write_spr},{read_spr | write_spr},{read_spr | write_spr},{read_spr | write_spr},{read_spr | write_spr},{read_spr | write_spr},{read_spr | write_spr},{read_spr | write_spr},{read_spr | write_spr},{read_spr | write_spr},{read_spr | write_spr},{read_spr | write_spr},{read_spr | write_spr},{read_spr | write_spr},{read_spr | write_spr},{read_spr | write_spr},{read_spr | write_spr},{read_spr | write_spr},{read_spr | write_spr},{read_spr | write_spr},{read_spr | write_spr},{read_spr | write_spr},{read_spr | write_spr},{read_spr | write_spr},{read_spr | write_spr},{read_spr | write_spr},{read_spr | write_spr},{read_spr | write_spr},{read_spr | write_spr},{read_spr | write_spr},{read_spr | write_spr}}; // // Decoding of groups // always @(spr_addr) case (spr_addr[15:11]) 5'b00000: unqualified_cs = 32'b00000000000000000000000000000001; 5'b00001: unqualified_cs = 32'b00000000000000000000000000000010; 5'b00010: unqualified_cs = 32'b00000000000000000000000000000100; 5'b00011: unqualified_cs = 32'b00000000000000000000000000001000; 5'b00100: unqualified_cs = 32'b00000000000000000000000000010000; 5'b00101: unqualified_cs = 32'b00000000000000000000000000100000; 5'b00110: unqualified_cs = 32'b00000000000000000000000001000000; 5'b00111: unqualified_cs = 32'b00000000000000000000000010000000; 5'b01000: unqualified_cs = 32'b00000000000000000000000100000000; 5'b01001: unqualified_cs = 32'b00000000000000000000001000000000; 5'b01010: unqualified_cs = 32'b00000000000000000000010000000000; 5'b01011: unqualified_cs = 32'b00000000000000000000100000000000; 5'b01100: unqualified_cs = 32'b00000000000000000001000000000000; 5'b01101: unqualified_cs = 32'b00000000000000000010000000000000; 5'b01110: unqualified_cs = 32'b00000000000000000100000000000000; 5'b01111: unqualified_cs = 32'b00000000000000001000000000000000; 5'b10000: unqualified_cs = 32'b00000000000000010000000000000000; 5'b10001: unqualified_cs = 32'b00000000000000100000000000000000; 5'b10010: unqualified_cs = 32'b00000000000001000000000000000000; 5'b10011: unqualified_cs = 32'b00000000000010000000000000000000; 5'b10100: unqualified_cs = 32'b00000000000100000000000000000000; 5'b10101: unqualified_cs = 32'b00000000001000000000000000000000; 5'b10110: unqualified_cs = 32'b00000000010000000000000000000000; 5'b10111: unqualified_cs = 32'b00000000100000000000000000000000; 5'b11000: unqualified_cs = 32'b00000001000000000000000000000000; 5'b11001: unqualified_cs = 32'b00000010000000000000000000000000; 5'b11010: unqualified_cs = 32'b00000100000000000000000000000000; 5'b11011: unqualified_cs = 32'b00001000000000000000000000000000; 5'b11100: unqualified_cs = 32'b00010000000000000000000000000000; 5'b11101: unqualified_cs = 32'b00100000000000000000000000000000; 5'b11110: unqualified_cs = 32'b01000000000000000000000000000000; 5'b11111: unqualified_cs = 32'b10000000000000000000000000000000; endcase // // SPRs System Group // // // What to write into SR // assign to_sr[`OR1200_SR_FO:`OR1200_SR_OV] = (branch_op == `OR1200_BRANCHOP_RFE) ? esr[`OR1200_SR_FO:`OR1200_SR_OV] : (write_spr && sr_sel) ? {1'b1, spr_dat_o[`OR1200_SR_FO-1:`OR1200_SR_OV]}: sr[`OR1200_SR_FO:`OR1200_SR_OV]; assign to_sr[`OR1200_SR_CY] = (branch_op == `OR1200_BRANCHOP_RFE) ? esr[`OR1200_SR_CY] : cy_we ? cyforw : (write_spr && sr_sel) ? spr_dat_o[`OR1200_SR_CY] : sr[`OR1200_SR_CY]; assign to_sr[`OR1200_SR_F] = (branch_op == `OR1200_BRANCHOP_RFE) ? esr[`OR1200_SR_F] : flag_we ? flagforw : (write_spr && sr_sel) ? spr_dat_o[`OR1200_SR_F] : sr[`OR1200_SR_F]; assign to_sr[`OR1200_SR_CE:`OR1200_SR_SM] = (branch_op == `OR1200_BRANCHOP_RFE) ? esr[`OR1200_SR_CE:`OR1200_SR_SM] : (write_spr && sr_sel) ? spr_dat_o[`OR1200_SR_CE:`OR1200_SR_SM]: sr[`OR1200_SR_CE:`OR1200_SR_SM]; // // Selects for system SPRs // assign cfgr_sel = (spr_cs[`OR1200_SPR_GROUP_SYS] && (spr_addr[10:4] == `OR1200_SPR_CFGR)); assign rf_sel = (spr_cs[`OR1200_SPR_GROUP_SYS] && (spr_addr[10:5] == `OR1200_SPR_RF)); assign npc_sel = (spr_cs[`OR1200_SPR_GROUP_SYS] && (spr_addr[10:0] == `OR1200_SPR_NPC)); assign ppc_sel = (spr_cs[`OR1200_SPR_GROUP_SYS] && (spr_addr[10:0] == `OR1200_SPR_PPC)); assign sr_sel = (spr_cs[`OR1200_SPR_GROUP_SYS] && (spr_addr[10:0] == `OR1200_SPR_SR)); assign epcr_sel = (spr_cs[`OR1200_SPR_GROUP_SYS] && (spr_addr[10:0] == `OR1200_SPR_EPCR)); assign eear_sel = (spr_cs[`OR1200_SPR_GROUP_SYS] && (spr_addr[10:0] == `OR1200_SPR_EEAR)); assign esr_sel = (spr_cs[`OR1200_SPR_GROUP_SYS] && (spr_addr[10:0] == `OR1200_SPR_ESR)); // // Write enables for system SPRs // assign sr_we = (write_spr && sr_sel) | (branch_op == `OR1200_BRANCHOP_RFE) | flag_we | cy_we; assign pc_we = (write_spr && (npc_sel | ppc_sel)); assign epcr_we = (write_spr && epcr_sel); assign eear_we = (write_spr && eear_sel); assign esr_we = (write_spr && esr_sel); // // Output from system SPRs // assign sys_data = (spr_dat_cfgr & {{read_spr & cfgr_sel}}) | (spr_dat_rf & {{read_spr & rf_sel}}) | (spr_dat_npc & {{read_spr & npc_sel}}) | (spr_dat_ppc & {{read_spr & ppc_sel}}) | ({{{16'b0000000000000000}},sr} & {{read_spr & sr_sel}}) | (epcr & {{read_spr & epcr_sel}}) | (eear & {{read_spr & eear_sel}}) | ({{{16'b0000000000000000}},esr} & {{read_spr & esr_sel}}); // // Flag alias // assign flag = sr[`OR1200_SR_F]; // // Carry alias // assign carry = sr[`OR1200_SR_CY]; // // Supervision register // always @(posedge clk) if (rst) sr <= {1'b1, `OR1200_SR_EPH_DEF, {{13'b0000000000000}}, 1'b1}; else if (except_started) begin sr[`OR1200_SR_SM] <= 1'b1; sr[`OR1200_SR_TEE] <= 1'b0; sr[`OR1200_SR_IEE] <= 1'b0; sr[`OR1200_SR_DME] <= 1'b0; sr[`OR1200_SR_IME] <= 1'b0; end else if (sr_we) sr <= to_sr[`OR1200_SR_WIDTH-1:0]; // // MTSPR/MFSPR interface // always @(sprs_op or spr_addr or sys_data or spr_dat_mac or spr_dat_pic or spr_dat_pm or spr_dat_dmmu or spr_dat_immu or spr_dat_du or spr_dat_tt) begin case (sprs_op) // synopsys parallel_case `OR1200_ALUOP_MTSR : begin write_spr = 1'b1; read_spr = 1'b0; to_wbmux = 32'b00000000000000000000000000000000; end `OR1200_ALUOP_MFSR : begin case (spr_addr[15:11]) // synopsys parallel_case `OR1200_SPR_GROUP_TT: to_wbmux = spr_dat_tt; `OR1200_SPR_GROUP_PIC: to_wbmux = spr_dat_pic; `OR1200_SPR_GROUP_PM: to_wbmux = spr_dat_pm; `OR1200_SPR_GROUP_DMMU: to_wbmux = spr_dat_dmmu; `OR1200_SPR_GROUP_IMMU: to_wbmux = spr_dat_immu; `OR1200_SPR_GROUP_MAC: to_wbmux = spr_dat_mac; `OR1200_SPR_GROUP_DU: to_wbmux = spr_dat_du; `OR1200_SPR_GROUP_SYS: to_wbmux = sys_data; default: to_wbmux = 32'b00000000000000000000000000000000; endcase write_spr = 1'b0; read_spr = 1'b1; end default : begin write_spr = 1'b0; read_spr = 1'b0; to_wbmux = 32'b00000000000000000000000000000000; end endcase end endmodule `define OR1200_NO_FREEZE 3'b000 `define OR1200_FREEZE_BYDC 3'b001 `define OR1200_FREEZE_BYMULTICYCLE 3'b010 `define OR1200_WAIT_LSU_TO_FINISH 3'b011 `define OR1200_WAIT_IC 3'b100 // // Freeze logic (stalls CPU pipeline, ifetcher etc.) // module or1200_freeze( // Clock and reset clk, rst, // Internal i/f multicycle, flushpipe, extend_flush, lsu_stall, if_stall, lsu_unstall, force_dslot_fetch, abort_ex, du_stall, mac_stall, genpc_freeze, if_freeze, id_freeze, ex_freeze, wb_freeze, icpu_ack_i, icpu_err_i ); // // I/O // input clk; input rst; input [`OR1200_MULTICYCLE_WIDTH-1:0] multicycle; input flushpipe; input extend_flush; input lsu_stall; input if_stall; input lsu_unstall; input force_dslot_fetch; input abort_ex; input du_stall; input mac_stall; output genpc_freeze; output if_freeze; output id_freeze; output ex_freeze; output wb_freeze; input icpu_ack_i; input icpu_err_i; // // Internal wires and regs // wire multicycle_freeze; reg [`OR1200_MULTICYCLE_WIDTH-1:0] multicycle_cnt; reg flushpipe_r; // // Pipeline freeze // // Rules how to create freeze signals: // 1. Not overwriting pipeline stages: // Freze signals at the beginning of pipeline (such as if_freeze) can be asserted more // often than freeze signals at the of pipeline (such as wb_freeze). In other words, wb_freeze must never // be asserted when ex_freeze is not. ex_freeze must never be asserted when id_freeze is not etc. // // 2. Inserting NOPs in the middle of pipeline only if supported: // At this time, only ex_freeze (and wb_freeze) can be deassrted when id_freeze (and if_freeze) are asserted. // This way NOP is asserted from stage ID into EX stage. // //assign genpc_freeze = du_stall | flushpipe_r | lsu_stall; assign genpc_freeze = du_stall | flushpipe_r; assign if_freeze = id_freeze | extend_flush; //assign id_freeze = (lsu_stall | (~lsu_unstall & if_stall) | multicycle_freeze | force_dslot_fetch) & ~flushpipe | du_stall; assign id_freeze = (lsu_stall | (~lsu_unstall & if_stall) | multicycle_freeze | force_dslot_fetch) | du_stall | mac_stall; assign ex_freeze = wb_freeze; //assign wb_freeze = (lsu_stall | (~lsu_unstall & if_stall) | multicycle_freeze) & ~flushpipe | du_stall | mac_stall; assign wb_freeze = (lsu_stall | (~lsu_unstall & if_stall) | multicycle_freeze) | du_stall | mac_stall | abort_ex; // // registered flushpipe // always @(posedge clk ) if (rst) flushpipe_r <= 1'b0; else if (icpu_ack_i | icpu_err_i) // else if (!if_stall) flushpipe_r <= flushpipe; else if (!flushpipe) flushpipe_r <= 1'b0; // // Multicycle freeze // assign multicycle_freeze = |multicycle_cnt; // // Multicycle counter // always @(posedge clk ) if (rst) multicycle_cnt <= 2'b00; else if (|multicycle_cnt) multicycle_cnt <= multicycle_cnt - 2'b01; else if (|multicycle & !ex_freeze) multicycle_cnt <= multicycle; endmodule `define OR1200_EXCEPTFSM_WIDTH 3 `define OR1200_EXCEPTFSM_IDLE 3'b000 `define OR1200_EXCEPTFSM_FLU1 3'b001 `define OR1200_EXCEPTFSM_FLU2 3'b010 `define OR1200_EXCEPTFSM_FLU3 3'b011 `define OR1200_EXCEPTFSM_FLU5 3'b101 `define OR1200_EXCEPTFSM_FLU4 3'b100 // // Exception recognition and sequencing // module or1200_except( // Clock and reset clk, rst, // Internal i/f sig_ibuserr, sig_dbuserr, sig_illegal, sig_align, sig_range, sig_dtlbmiss, sig_dmmufault, sig_int, sig_syscall, sig_trap, sig_itlbmiss, sig_immufault, sig_tick, branch_taken,icpu_ack_i, icpu_err_i, dcpu_ack_i, dcpu_err_i, genpc_freeze, id_freeze, ex_freeze, wb_freeze, if_stall, if_pc, id_pc, lr_sav, flushpipe, extend_flush, except_type, except_start, except_started, except_stop, ex_void, spr_dat_ppc, spr_dat_npc, datain, du_dsr, epcr_we, eear_we, esr_we, pc_we, epcr, eear, esr, lsu_addr, sr_we, to_sr, sr, abort_ex ); // // I/O // input clk; input rst; input sig_ibuserr; input sig_dbuserr; input sig_illegal; input sig_align; input sig_range; input sig_dtlbmiss; input sig_dmmufault; input sig_int; input sig_syscall; input sig_trap; input sig_itlbmiss; input sig_immufault; input sig_tick; input branch_taken; input genpc_freeze; input id_freeze; input ex_freeze; input wb_freeze; input if_stall; input [31:0] if_pc; output [31:0] id_pc; output [31:2] lr_sav; input [31:0] datain; input [`OR1200_DU_DSR_WIDTH-1:0] du_dsr; input epcr_we; input eear_we; input esr_we; input pc_we; output [31:0] epcr; output [31:0] eear; output [`OR1200_SR_WIDTH-1:0] esr; input [`OR1200_SR_WIDTH-1:0] to_sr; input sr_we; input [`OR1200_SR_WIDTH-1:0] sr; input [31:0] lsu_addr; output flushpipe; output extend_flush; output [`OR1200_EXCEPT_WIDTH-1:0] except_type; output except_start; output except_started; output [12:0] except_stop; input ex_void; output [31:0] spr_dat_ppc; output [31:0] spr_dat_npc; output abort_ex; input icpu_ack_i; input icpu_err_i; input dcpu_ack_i; input dcpu_err_i; // // Internal regs and wires // reg [`OR1200_EXCEPT_WIDTH-1:0] except_type; reg [31:0] id_pc; reg [31:0] ex_pc; reg [31:0] wb_pc; reg [31:0] epcr; reg [31:0] eear; reg [`OR1200_SR_WIDTH-1:0] esr; reg [2:0] id_exceptflags; reg [2:0] ex_exceptflags; reg [`OR1200_EXCEPTFSM_WIDTH-1:0] state; reg extend_flush; reg extend_flush_last; reg ex_dslot; reg delayed1_ex_dslot; reg delayed2_ex_dslot; wire except_started; wire [12:0] except_trig; wire except_flushpipe; reg [2:0] delayed_iee; reg [2:0] delayed_tee; wire int_pending; wire tick_pending; // // Simple combinatorial logic // assign except_started = extend_flush & except_start; assign lr_sav = ex_pc[31:2]; assign spr_dat_ppc = wb_pc; assign spr_dat_npc = ex_void ? id_pc : ex_pc; assign except_start = (except_type != 4'b0000) & extend_flush; assign int_pending = sig_int & sr[`OR1200_SR_IEE] & delayed_iee[2] & ~ex_freeze & ~branch_taken & ~ex_dslot & ~sr_we; assign tick_pending = sig_tick & sr[`OR1200_SR_TEE] & ~ex_freeze & ~branch_taken & ~ex_dslot & ~sr_we; assign abort_ex = sig_dbuserr | sig_dmmufault | sig_dtlbmiss | sig_align | sig_illegal; // Abort write into RF by load & other instructions // // Order defines exception detection priority // assign except_trig = { tick_pending & ~du_dsr[`OR1200_DU_DSR_TTE], int_pending & ~du_dsr[`OR1200_DU_DSR_IE], ex_exceptflags[1] & ~du_dsr[`OR1200_DU_DSR_IME], ex_exceptflags[0] & ~du_dsr[`OR1200_DU_DSR_IPFE], ex_exceptflags[2] & ~du_dsr[`OR1200_DU_DSR_BUSEE], sig_illegal & ~du_dsr[`OR1200_DU_DSR_IIE], sig_align & ~du_dsr[`OR1200_DU_DSR_AE], sig_dtlbmiss & ~du_dsr[`OR1200_DU_DSR_DME], sig_dmmufault & ~du_dsr[`OR1200_DU_DSR_DPFE], sig_dbuserr & ~du_dsr[`OR1200_DU_DSR_BUSEE], sig_range & ~du_dsr[`OR1200_DU_DSR_RE], sig_trap & ~du_dsr[`OR1200_DU_DSR_TE] & ~ex_freeze, sig_syscall & ~du_dsr[`OR1200_DU_DSR_SCE] & ~ex_freeze }; assign except_stop = { tick_pending & du_dsr[`OR1200_DU_DSR_TTE], int_pending & du_dsr[`OR1200_DU_DSR_IE], ex_exceptflags[1] & du_dsr[`OR1200_DU_DSR_IME], ex_exceptflags[0] & du_dsr[`OR1200_DU_DSR_IPFE], ex_exceptflags[2] & du_dsr[`OR1200_DU_DSR_BUSEE], sig_illegal & du_dsr[`OR1200_DU_DSR_IIE], sig_align & du_dsr[`OR1200_DU_DSR_AE], sig_dtlbmiss & du_dsr[`OR1200_DU_DSR_DME], sig_dmmufault & du_dsr[`OR1200_DU_DSR_DPFE], sig_dbuserr & du_dsr[`OR1200_DU_DSR_BUSEE], sig_range & du_dsr[`OR1200_DU_DSR_RE], sig_trap & du_dsr[`OR1200_DU_DSR_TE] & ~ex_freeze, sig_syscall & du_dsr[`OR1200_DU_DSR_SCE] & ~ex_freeze }; // // PC and Exception flags pipelines // always @(posedge clk ) begin if (rst) begin id_pc <= 32'b00000000000000000000000000000000; id_exceptflags <= 3'b000; end else if (flushpipe) begin id_pc <= 32'h00000000; id_exceptflags <= 3'b000; end else if (!id_freeze) begin id_pc <= if_pc; id_exceptflags <= { sig_ibuserr, sig_itlbmiss, sig_immufault }; end end // // delayed_iee // // SR[IEE] should not enable interrupts right away // when it is restored with l.rfe. Instead delayed_iee // together with SR[IEE] enables interrupts once // pipeline is again ready. // always @(posedge clk) if (rst) delayed_iee <= 3'b000; else if (!sr[`OR1200_SR_IEE]) delayed_iee <= 3'b000; else delayed_iee <= {delayed_iee[1:0], 1'b1}; // // delayed_tee // // SR[TEE] should not enable tick exceptions right away // when it is restored with l.rfe. Instead delayed_tee // together with SR[TEE] enables tick exceptions once // pipeline is again ready. // always @( posedge clk) if (rst) delayed_tee <= 3'b000; else if (!sr[`OR1200_SR_TEE]) delayed_tee <= 3'b000; else delayed_tee <= {delayed_tee[1:0], 1'b1}; // // PC and Exception flags pipelines // always @(posedge clk ) begin if (rst) begin ex_dslot <= 1'b0; ex_pc <= 32'd0; ex_exceptflags <= 3'b000; delayed1_ex_dslot <= 1'b0; delayed2_ex_dslot <= 1'b0; end else if (flushpipe) begin ex_dslot <= 1'b0; ex_pc <= 32'h00000000; ex_exceptflags <= 3'b000; delayed1_ex_dslot <= 1'b0; delayed2_ex_dslot <= 1'b0; end else if (!ex_freeze & id_freeze) begin ex_dslot <= 1'b0; ex_pc <= id_pc; ex_exceptflags <= 3'b000; delayed1_ex_dslot <= ex_dslot; delayed2_ex_dslot <= delayed1_ex_dslot; end else if (!ex_freeze) begin ex_dslot <= branch_taken; ex_pc <= id_pc; ex_exceptflags <= id_exceptflags; delayed1_ex_dslot <= ex_dslot; delayed2_ex_dslot <= delayed1_ex_dslot; end end // // PC and Exception flags pipelines // always @(posedge clk ) begin if (rst) begin wb_pc <= 32'b00000000000000000000000000000000; end else if (!wb_freeze) begin wb_pc <= ex_pc; end end // // Flush pipeline // assign flushpipe = except_flushpipe | pc_we | extend_flush; // // We have started execution of exception handler: // 1. Asserted for 3 clock cycles // 2. Don't execute any instruction that is still in pipeline and is not part of exception handler // assign except_flushpipe = |except_trig & ~|state; // // Exception FSM that sequences execution of exception handler // // except_type signals which exception handler we start fetching in: // 1. Asserted in next clock cycle after exception is recognized // always @(posedge clk ) begin if (rst) begin state <= `OR1200_EXCEPTFSM_IDLE; except_type <= 4'b0000; extend_flush <= 1'b0; epcr <= 32'b00000000000000000000000000000000; eear <= 32'b00000000000000000000000000000000; esr <= {{1'b1, 1'b0},{1'b0},{1'b0},{1'b0},{1'b0},{1'b0},{1'b0},{1'b0},{1'b0},{1'b0},{1'b0},{1'b0},{1'b0},{1'b0},{1'b0},{1'b0},{1'b0},{1'b0},{1'b0},{1'b0},{1'b0},{1'b0},{1'b0},{1'b0},{1'b0},{1'b0},{1'b0},{1'b0},{1'b0},{1'b0}, {1'b1}}; extend_flush_last <= 1'b0; end else begin case (state) `OR1200_EXCEPTFSM_IDLE: if (except_flushpipe) begin state <= `OR1200_EXCEPTFSM_FLU1; extend_flush <= 1'b1; esr <= sr_we ? to_sr : sr; if (except_trig[12] == 1) begin except_type <= `OR1200_EXCEPT_TICK; epcr <= ex_dslot ? wb_pc : delayed1_ex_dslot ? id_pc : delayed2_ex_dslot ? id_pc : id_pc; end else if (except_trig[12] == 0 && except_trig[11] == 0) begin except_type <= `OR1200_EXCEPT_INT; epcr <= ex_dslot ? wb_pc : delayed1_ex_dslot ? id_pc : delayed2_ex_dslot ? id_pc : id_pc; end else if (except_trig[12] == 0 && except_trig[11] == 0 && except_trig[10] == 1) begin except_type <= `OR1200_EXCEPT_ITLBMISS; // // itlb miss exception and active ex_dslot caused wb_pc to put into eear instead of +4 address of ex_pc (or id_pc since it was equal to ex_pc?) // eear <= ex_dslot ? wb_pc : delayed1_ex_dslot ? id_pc : delayed2_ex_dslot ? id_pc : id_pc; // mmu-icdc-O2 ex_pc only OK when no ex_dslot eear <= ex_dslot ? ex_pc : delayed1_ex_dslot ? id_pc : delayed2_ex_dslot ? id_pc : id_pc; // mmu-icdc-O2 ex_pc only OK when no ex_dslot epcr <= ex_dslot ? wb_pc : delayed1_ex_dslot ? id_pc : delayed2_ex_dslot ? id_pc : id_pc; eear <= ex_dslot ? ex_pc : ex_pc; epcr <= ex_dslot ? wb_pc : ex_pc; // eear <= ex_dslot ? ex_pc : delayed1_ex_dslot ? id_pc : delayed2_ex_dslot ? id_pc : id_pc; // epcr <= ex_dslot ? wb_pc : delayed1_ex_dslot ? id_pc : delayed2_ex_dslot ? id_pc : id_pc; end else begin except_type <= 4'b0000; end end else if (pc_we) begin state <= `OR1200_EXCEPTFSM_FLU1; extend_flush <= 1'b1; end else begin if (epcr_we) epcr <= datain; if (eear_we) eear <= datain; if (esr_we) esr <= {1'b1, datain[`OR1200_SR_WIDTH-2:0]}; end `OR1200_EXCEPTFSM_FLU1: if (icpu_ack_i | icpu_err_i | genpc_freeze) state <= `OR1200_EXCEPTFSM_FLU2; `OR1200_EXCEPTFSM_FLU2: state <= `OR1200_EXCEPTFSM_FLU3; `OR1200_EXCEPTFSM_FLU3: begin state <= `OR1200_EXCEPTFSM_FLU4; end `OR1200_EXCEPTFSM_FLU4: begin state <= `OR1200_EXCEPTFSM_FLU5; extend_flush <= 1'b0; extend_flush_last <= 1'b0; // damjan end default: begin if (!if_stall && !id_freeze) begin state <= `OR1200_EXCEPTFSM_IDLE; except_type <= 4'b0000; extend_flush_last <= 1'b0; end end endcase end end wire unused; assign unused = sig_range | sig_syscall | sig_trap | dcpu_ack_i| dcpu_err_i | du_dsr | lsu_addr; endmodule module or1200_cfgr( // RISC Internal Interface spr_addr, spr_dat_o ); // // RISC Internal Interface // input [31:0] spr_addr; // SPR Address output [31:0] spr_dat_o; // SPR Read Data // // Internal wires & registers // reg [31:0] spr_dat_o; // SPR Read Data // // Implementation of VR, UPR and configuration registers // always @(spr_addr) if (~|spr_addr[31:4]) case(spr_addr[3:0]) // synopsys parallel_case `OR1200_SPRGRP_SYS_VR: begin spr_dat_o[5:0] = `OR1200_VR_REV; spr_dat_o[16:6] = `OR1200_VR_RES1; spr_dat_o[23:17] = `OR1200_VR_CFG; spr_dat_o[31:24] = `OR1200_VR_VER; end `OR1200_SPRGRP_SYS_UPR: begin spr_dat_o[`OR1200_UPR_UP_BITS] = `OR1200_UPR_UP; spr_dat_o[`OR1200_UPR_DCP_BITS] = `OR1200_UPR_DCP; spr_dat_o[`OR1200_UPR_ICP_BITS] = `OR1200_UPR_ICP; spr_dat_o[`OR1200_UPR_DMP_BITS] = `OR1200_UPR_DMP; spr_dat_o[`OR1200_UPR_IMP_BITS] = `OR1200_UPR_IMP; spr_dat_o[`OR1200_UPR_MP_BITS] = `OR1200_UPR_MP; spr_dat_o[`OR1200_UPR_DUP_BITS] = `OR1200_UPR_DUP; spr_dat_o[`OR1200_UPR_PCUP_BITS] = `OR1200_UPR_PCUP; spr_dat_o[`OR1200_UPR_PMP_BITS] = `OR1200_UPR_PMP; spr_dat_o[`OR1200_UPR_PICP_BITS] = `OR1200_UPR_PICP; spr_dat_o[`OR1200_UPR_TTP_BITS] = `OR1200_UPR_TTP; spr_dat_o[23:11] = `OR1200_UPR_RES1; spr_dat_o[31:24] = `OR1200_UPR_CUP; end `OR1200_SPRGRP_SYS_CPUCFGR: begin spr_dat_o[3:0] = `OR1200_CPUCFGR_NSGF; spr_dat_o[`OR1200_CPUCFGR_HGF_BITS] = `OR1200_CPUCFGR_HGF; spr_dat_o[`OR1200_CPUCFGR_OB32S_BITS] = `OR1200_CPUCFGR_OB32S; spr_dat_o[`OR1200_CPUCFGR_OB64S_BITS] = `OR1200_CPUCFGR_OB64S; spr_dat_o[`OR1200_CPUCFGR_OF32S_BITS] = `OR1200_CPUCFGR_OF32S; spr_dat_o[`OR1200_CPUCFGR_OF64S_BITS] = `OR1200_CPUCFGR_OF64S; spr_dat_o[`OR1200_CPUCFGR_OV64S_BITS] = `OR1200_CPUCFGR_OV64S; spr_dat_o[31:10] = `OR1200_CPUCFGR_RES1; end `OR1200_SPRGRP_SYS_DMMUCFGR: begin spr_dat_o[1:0] = `OR1200_DMMUCFGR_NTW; spr_dat_o[4:2] = `OR1200_DMMUCFGR_NTS; spr_dat_o[7:5] = `OR1200_DMMUCFGR_NAE; spr_dat_o[`OR1200_DMMUCFGR_CRI_BITS] = `OR1200_DMMUCFGR_CRI; spr_dat_o[`OR1200_DMMUCFGR_PRI_BITS] = `OR1200_DMMUCFGR_PRI; spr_dat_o[`OR1200_DMMUCFGR_TEIRI_BITS] = `OR1200_DMMUCFGR_TEIRI; spr_dat_o[`OR1200_DMMUCFGR_HTR_BITS] = `OR1200_DMMUCFGR_HTR; spr_dat_o[31:12] = `OR1200_DMMUCFGR_RES1; end `OR1200_SPRGRP_SYS_IMMUCFGR: begin spr_dat_o[1:0] = `OR1200_IMMUCFGR_NTW; spr_dat_o[4:2] = `OR1200_IMMUCFGR_NTS; spr_dat_o[7:5] = `OR1200_IMMUCFGR_NAE; spr_dat_o[`OR1200_IMMUCFGR_CRI_BITS] = `OR1200_IMMUCFGR_CRI; spr_dat_o[`OR1200_IMMUCFGR_PRI_BITS] = `OR1200_IMMUCFGR_PRI; spr_dat_o[`OR1200_IMMUCFGR_TEIRI_BITS] = `OR1200_IMMUCFGR_TEIRI; spr_dat_o[`OR1200_IMMUCFGR_HTR_BITS] = `OR1200_IMMUCFGR_HTR; spr_dat_o[31:12] = `OR1200_IMMUCFGR_RES1; end `OR1200_SPRGRP_SYS_DCCFGR: begin spr_dat_o[2:0] = `OR1200_DCCFGR_NCW; spr_dat_o[6:3] = `OR1200_DCCFGR_NCS; spr_dat_o[`OR1200_DCCFGR_CBS_BITS] = `OR1200_DCCFGR_CBS; spr_dat_o[`OR1200_DCCFGR_CWS_BITS] = `OR1200_DCCFGR_CWS; spr_dat_o[`OR1200_DCCFGR_CCRI_BITS] = `OR1200_DCCFGR_CCRI; spr_dat_o[`OR1200_DCCFGR_CBIRI_BITS] = `OR1200_DCCFGR_CBIRI; spr_dat_o[`OR1200_DCCFGR_CBPRI_BITS] = `OR1200_DCCFGR_CBPRI; spr_dat_o[`OR1200_DCCFGR_CBLRI_BITS] = `OR1200_DCCFGR_CBLRI; spr_dat_o[`OR1200_DCCFGR_CBFRI_BITS] = `OR1200_DCCFGR_CBFRI; spr_dat_o[`OR1200_DCCFGR_CBWBRI_BITS] = `OR1200_DCCFGR_CBWBRI; spr_dat_o[31:15] = `OR1200_DCCFGR_RES1; end `OR1200_SPRGRP_SYS_ICCFGR: begin spr_dat_o[2:0] = `OR1200_ICCFGR_NCW; spr_dat_o[6:3] = `OR1200_ICCFGR_NCS; spr_dat_o[`OR1200_ICCFGR_CBS_BITS] = `OR1200_ICCFGR_CBS; spr_dat_o[`OR1200_ICCFGR_CWS_BITS] = `OR1200_ICCFGR_CWS; spr_dat_o[`OR1200_ICCFGR_CCRI_BITS] = `OR1200_ICCFGR_CCRI; spr_dat_o[`OR1200_ICCFGR_CBIRI_BITS] = `OR1200_ICCFGR_CBIRI; spr_dat_o[`OR1200_ICCFGR_CBPRI_BITS] = `OR1200_ICCFGR_CBPRI; spr_dat_o[`OR1200_ICCFGR_CBLRI_BITS] = `OR1200_ICCFGR_CBLRI; spr_dat_o[`OR1200_ICCFGR_CBFRI_BITS] = `OR1200_ICCFGR_CBFRI; spr_dat_o[`OR1200_ICCFGR_CBWBRI_BITS] = `OR1200_ICCFGR_CBWBRI; spr_dat_o[31:15] = `OR1200_ICCFGR_RES1; end `OR1200_SPRGRP_SYS_DCFGR: begin spr_dat_o[2:0] = `OR1200_DCFGR_NDP; spr_dat_o[3] = `OR1200_DCFGR_WPCI; spr_dat_o[31:4] = `OR1200_DCFGR_RES1; end default: spr_dat_o = 32'h00000000; endcase // endmodule module or1200_wbmux( // Clock and reset clk, rst, // Internal i/f wb_freeze, rfwb_op, muxin_a, muxin_b, muxin_c, muxin_d, muxout, muxreg, muxreg_valid ); //parameter width = `OR1200_OPERAND_WIDTH; // // I/O // // // Clock and reset // input clk; input rst; // // Internal i/f // input wb_freeze; input [`OR1200_RFWBOP_WIDTH-1:0] rfwb_op; input [32-1:0] muxin_a; input [32-1:0] muxin_b; input [32-1:0] muxin_c; input [32-1:0] muxin_d; output [32-1:0] muxout; output [32-1:0] muxreg; output muxreg_valid; // // Internal wires and regs // reg [32-1:0] muxout; reg [32-1:0] muxreg; reg muxreg_valid; // // Registered output from the write-back multiplexer // always @(posedge clk) begin if (rst) begin muxreg <= 32'b00000000000000000000000000000000; muxreg_valid <= 1'b0; end else if (!wb_freeze) begin muxreg <= muxout; muxreg_valid <= rfwb_op[0]; end end // // Write-back multiplexer // always @(muxin_a or muxin_b or muxin_c or muxin_d or rfwb_op) begin case(rfwb_op[`OR1200_RFWBOP_WIDTH-1:1]) 2'b00: muxout = muxin_a; 2'b01: begin muxout = muxin_b; end 2'b10: begin muxout = muxin_c; end 2'b11: begin muxout = muxin_d + 32'b00000000000000000000000000001000; end endcase end endmodule module or1200_lsu( // Internal i/f addrbase, addrofs, lsu_op, lsu_datain, lsu_dataout, lsu_stall, lsu_unstall, du_stall, except_align, except_dtlbmiss, except_dmmufault, except_dbuserr, // External i/f to DC dcpu_adr_o, dcpu_cycstb_o, dcpu_we_o, dcpu_sel_o, dcpu_tag_o, dcpu_dat_o, dcpu_dat_i, dcpu_ack_i, dcpu_rty_i, dcpu_err_i, dcpu_tag_i ); //parameter dw = `OR1200_OPERAND_WIDTH; //parameter aw = `OR1200_REGFILE_ADDR_WIDTH; // // I/O // // // Internal i/f // input [31:0] addrbase; input [31:0] addrofs; input [`OR1200_LSUOP_WIDTH-1:0] lsu_op; input [`OR1200_OPERAND_WIDTH-1:0] lsu_datain; output [`OR1200_OPERAND_WIDTH-1:0] lsu_dataout; output lsu_stall; output lsu_unstall; input du_stall; output except_align; output except_dtlbmiss; output except_dmmufault; output except_dbuserr; // // External i/f to DC // output [31:0] dcpu_adr_o; output dcpu_cycstb_o; output dcpu_we_o; output [3:0] dcpu_sel_o; output [3:0] dcpu_tag_o; output [31:0] dcpu_dat_o; input [31:0] dcpu_dat_i; input dcpu_ack_i; input dcpu_rty_i; input dcpu_err_i; input [3:0] dcpu_tag_i; // // Internal wires/regs // reg [3:0] dcpu_sel_o; // // Internal I/F assignments // assign lsu_stall = dcpu_rty_i & dcpu_cycstb_o; assign lsu_unstall = dcpu_ack_i; assign except_align = ((lsu_op == `OR1200_LSUOP_SH) | (lsu_op == `OR1200_LSUOP_LHZ) | (lsu_op == `OR1200_LSUOP_LHS)) & dcpu_adr_o[0] | ((lsu_op == `OR1200_LSUOP_SW) | (lsu_op == `OR1200_LSUOP_LWZ) | (lsu_op == `OR1200_LSUOP_LWS)) & |dcpu_adr_o[1:0]; assign except_dtlbmiss = dcpu_err_i & (dcpu_tag_i == `OR1200_DTAG_TE); assign except_dmmufault = dcpu_err_i & (dcpu_tag_i == `OR1200_DTAG_PE); assign except_dbuserr = dcpu_err_i & (dcpu_tag_i == `OR1200_DTAG_BE); // // External I/F assignments // assign dcpu_adr_o = addrbase + addrofs; assign dcpu_cycstb_o = du_stall | lsu_unstall | except_align ? 1'b0 : |lsu_op; assign dcpu_we_o = lsu_op[3]; assign dcpu_tag_o = dcpu_cycstb_o ? `OR1200_DTAG_ND : `OR1200_DTAG_IDLE; always @(lsu_op or dcpu_adr_o) case({lsu_op, dcpu_adr_o[1:0]}) {`OR1200_LSUOP_SB, 2'b00} : dcpu_sel_o = 4'b1000; {`OR1200_LSUOP_SB, 2'b01} : dcpu_sel_o = 4'b0100; {`OR1200_LSUOP_SB, 2'b10} : dcpu_sel_o = 4'b0010; {`OR1200_LSUOP_SB, 2'b11} : dcpu_sel_o = 4'b0001; {`OR1200_LSUOP_SH, 2'b00} : dcpu_sel_o = 4'b1100; {`OR1200_LSUOP_SH, 2'b10} : dcpu_sel_o = 4'b0011; {`OR1200_LSUOP_SW, 2'b00} : dcpu_sel_o = 4'b1111; {`OR1200_LSUOP_LBZ, 2'b00} : dcpu_sel_o = 4'b1000; {`OR1200_LSUOP_LBS, 2'b00} : dcpu_sel_o = 4'b1000; {`OR1200_LSUOP_LBZ, 2'b01}: dcpu_sel_o = 4'b0100; {`OR1200_LSUOP_LBS, 2'b01} : dcpu_sel_o = 4'b0100; {`OR1200_LSUOP_LBZ, 2'b10}: dcpu_sel_o = 4'b0010; {`OR1200_LSUOP_LBS, 2'b10} : dcpu_sel_o = 4'b0010; {`OR1200_LSUOP_LBZ, 2'b11}: dcpu_sel_o = 4'b0001; {`OR1200_LSUOP_LBS, 2'b11} : dcpu_sel_o = 4'b0001; {`OR1200_LSUOP_LHZ, 2'b00}: dcpu_sel_o = 4'b1100; {`OR1200_LSUOP_LHS, 2'b00} : dcpu_sel_o = 4'b1100; {`OR1200_LSUOP_LHZ, 2'b10}: dcpu_sel_o = 4'b0011; {`OR1200_LSUOP_LHS, 2'b10} : dcpu_sel_o = 4'b0011; {`OR1200_LSUOP_LWZ, 2'b00}: dcpu_sel_o = 4'b1111; {4'b1111, 2'b00} : dcpu_sel_o = 4'b1111; default : dcpu_sel_o = 4'b0000; endcase // // Instantiation of Memory-to-regfile aligner // or1200_mem2reg or1200_mem2reg( .addr(dcpu_adr_o[1:0]), .lsu_op(lsu_op), .memdata(dcpu_dat_i), .regdata(lsu_dataout) ); // // Instantiation of Regfile-to-memory aligner // or1200_reg2mem or1200_reg2mem( .addr(dcpu_adr_o[1:0]), .lsu_op(lsu_op), .regdata(lsu_datain), .memdata(dcpu_dat_o) ); endmodule module or1200_reg2mem(addr, lsu_op, regdata, memdata); //parameter width = `OR1200_OPERAND_WIDTH; // // I/O // input [1:0] addr; input [`OR1200_LSUOP_WIDTH-1:0] lsu_op; input [32-1:0] regdata; output [32-1:0] memdata; // // Internal regs and wires // reg [7:0] memdata_hh; reg [7:0] memdata_hl; reg [7:0] memdata_lh; reg [7:0] memdata_ll; assign memdata = {memdata_hh, memdata_hl, memdata_lh, memdata_ll}; // // Mux to memdata[31:24] // always @(lsu_op or addr or regdata) begin case({lsu_op, addr[1:0]}) // synopsys parallel_case {`OR1200_LSUOP_SB, 2'b00} : memdata_hh = regdata[7:0]; {`OR1200_LSUOP_SH, 2'b00} : memdata_hh = regdata[15:8]; default : memdata_hh = regdata[31:24]; endcase end // // Mux to memdata[23:16] // always @(lsu_op or addr or regdata) begin case({lsu_op, addr[1:0]}) // synopsys parallel_case {`OR1200_LSUOP_SW, 2'b00} : memdata_hl = regdata[23:16]; default : memdata_hl = regdata[7:0]; endcase end // // Mux to memdata[15:8] // always @(lsu_op or addr or regdata) begin case({lsu_op, addr[1:0]}) // synopsys parallel_case {`OR1200_LSUOP_SB, 2'b10} : memdata_lh = regdata[7:0]; default : memdata_lh = regdata[15:8]; endcase end // // Mux to memdata[7:0] // always @(regdata) memdata_ll = regdata[7:0]; endmodule module or1200_mem2reg(addr, lsu_op, memdata, regdata); //parameter width = `OR1200_OPERAND_WIDTH; // // I/O // input [1:0] addr; input [`OR1200_LSUOP_WIDTH-1:0] lsu_op; input [32-1:0] memdata; output [32-1:0] regdata; wire [32-1:0] regdata; // // In the past faster implementation of mem2reg (today probably slower) // reg [7:0] regdata_hh; reg [7:0] regdata_hl; reg [7:0] regdata_lh; reg [7:0] regdata_ll; reg [32-1:0] aligned; reg [3:0] sel_byte0, sel_byte1, sel_byte2, sel_byte3; assign regdata = {regdata_hh, regdata_hl, regdata_lh, regdata_ll}; // // Byte select 0 // always @(addr or lsu_op) begin case({lsu_op[2:0], addr}) // synopsys parallel_case {3'b011, 2'b00}: // lbz/lbs 0 sel_byte0 = `OR1200_M2R_BYTE3; // take byte 3 {3'b011, 2'b01}: sel_byte0 = `OR1200_M2R_BYTE2; {3'b101, 2'b00}: // lhz/lhs 0 sel_byte0 = `OR1200_M2R_BYTE2; // take byte 2 {3'b011, 2'b10}: // lbz/lbs 2 sel_byte0 = `OR1200_M2R_BYTE1; // take byte 1 default: // all other cases sel_byte0 = `OR1200_M2R_BYTE0; // take byte 0 endcase end // // Byte select 1 // always @(addr or lsu_op) begin case({lsu_op[2:0], addr}) // synopsys parallel_case {3'b010, 2'b00}: // lbz sel_byte1 = `OR1200_M2R_ZERO; // zero extend {3'b011, 2'b00}: // lbs 0 sel_byte1 = `OR1200_M2R_EXTB3; // sign extend from byte 3 {3'b011, 2'b01}: // lbs 1 sel_byte1 = `OR1200_M2R_EXTB2; // sign extend from byte 2 {3'b011, 2'b10}: // lbs 2 sel_byte1 = `OR1200_M2R_EXTB1; // sign extend from byte 1 {3'b011, 2'b11}: // lbs 3 sel_byte1 = `OR1200_M2R_EXTB0; // sign extend from byte 0 {3'b100, 2'b00}: // lhz/lhs 0 sel_byte1 = `OR1200_M2R_BYTE3; // take byte 3 default: // all other cases sel_byte1 = `OR1200_M2R_BYTE1; // take byte 1 endcase end // // Byte select 2 // always @(addr or lsu_op) begin case({lsu_op[2:0], addr}) // synopsys parallel_case {3'b010, 2'b00}: sel_byte2 = `OR1200_M2R_ZERO; // lbz {3'b100, 2'b00}: // lhz sel_byte2 = `OR1200_M2R_ZERO; // zero extend {3'b011, 2'b00}: sel_byte2 = `OR1200_M2R_EXTB3; // sign extend from byte 3 {3'b101, 2'b00}: // lhs 0 sel_byte2 = `OR1200_M2R_EXTB3; // sign extend from byte 3 {3'b011, 2'b01}: // lbs 1 sel_byte2 = `OR1200_M2R_EXTB2; // sign extend from byte 2 {3'b011, 2'b10}: sel_byte2 = `OR1200_M2R_EXTB1; {3'b101, 2'b10}: // lhs 0 sel_byte2 = `OR1200_M2R_EXTB1; // sign extend from byte 1 {3'b011, 2'b11}: // lbs 3 sel_byte2 = `OR1200_M2R_EXTB0; // sign extend from byte 0 default: // all other cases sel_byte2 = `OR1200_M2R_BYTE2; // take byte 2 endcase end // // Byte select 3 // always @(addr or lsu_op) begin case({lsu_op[2:0], addr}) // synopsys parallel_case {3'b010, 2'b00}: sel_byte3 = `OR1200_M2R_ZERO; // zero extend // lbz {3'b100, 2'b00}: // lhz sel_byte3 = `OR1200_M2R_ZERO; // zero extend {3'b011, 2'b00}: sel_byte3 = `OR1200_M2R_EXTB3; {3'b101, 2'b00}: // lhs 0 sel_byte3 = `OR1200_M2R_EXTB3; // sign extend from byte 3 {3'b011, 2'b01}: // lbs 1 sel_byte3 = `OR1200_M2R_EXTB2; // sign extend from byte 2 {3'b011, 2'b10}: sel_byte3 = `OR1200_M2R_EXTB1; {3'b101, 2'b10}: // lhs 0 sel_byte3 = `OR1200_M2R_EXTB1; // sign extend from byte 1 {3'b011, 2'b11}: // lbs 3 sel_byte3 = `OR1200_M2R_EXTB0; // sign extend from byte 0 default: // all other cases sel_byte3 = `OR1200_M2R_BYTE3; // take byte 3 endcase end // // Byte 0 // always @(sel_byte0 or memdata) begin case(sel_byte0) `OR1200_M2R_BYTE0: begin regdata_ll = memdata[7:0]; end `OR1200_M2R_BYTE1: begin regdata_ll = memdata[15:8]; end `OR1200_M2R_BYTE2: begin regdata_ll = memdata[23:16]; end default: begin regdata_ll = memdata[31:24]; end endcase end // // Byte 1 // always @(sel_byte1 or memdata) begin case(sel_byte1) `OR1200_M2R_ZERO: begin regdata_lh = 8'h00; end `OR1200_M2R_BYTE1: begin regdata_lh = memdata[15:8]; end `OR1200_M2R_BYTE3: begin regdata_lh = memdata[31:24]; end `OR1200_M2R_EXTB0: begin regdata_lh = {{memdata[7]},{memdata[7]},{memdata[7]},{memdata[7]},{memdata[7]},{memdata[7]},{memdata[7]},{memdata[7]}}; end `OR1200_M2R_EXTB1: begin regdata_lh = {{memdata[15]},{memdata[15]},{memdata[15]},{memdata[15]},{memdata[15]},{memdata[15]},{memdata[15]},{memdata[15]}}; end `OR1200_M2R_EXTB2: begin regdata_lh = {{memdata[23]},{memdata[23]},{memdata[23]},{memdata[23]},{memdata[23]},{memdata[23]},{memdata[23]},{memdata[23]}}; end default: begin regdata_lh = {{memdata[31]},{memdata[31]},{memdata[31]},{memdata[31]},{memdata[31]},{memdata[31]},{memdata[31]},{memdata[31]}}; end endcase end // // Byte 2 // always @(sel_byte2 or memdata) begin case(sel_byte2) `OR1200_M2R_ZERO: begin regdata_hl = 8'h00; end `OR1200_M2R_BYTE2: begin regdata_hl = memdata[23:16]; end `OR1200_M2R_EXTB0: begin regdata_hl = {{memdata[7]},{memdata[7]},{memdata[7]},{memdata[7]},{memdata[7]},{memdata[7]},{memdata[7]},{memdata[7]}}; end `OR1200_M2R_EXTB1: begin regdata_hl = {{memdata[15]},{memdata[15]},{memdata[15]},{memdata[15]},{memdata[15]},{memdata[15]},{memdata[15]},{memdata[15]}}; end `OR1200_M2R_EXTB2: begin regdata_hl = {{memdata[23]},{memdata[23]},{memdata[23]},{memdata[23]},{memdata[23]},{memdata[23]},{memdata[23]},{memdata[23]}}; end default: begin regdata_hl = {{memdata[31]},{memdata[31]},{memdata[31]},{memdata[31]},{memdata[31]},{memdata[31]},{memdata[31]},{memdata[31]}}; end endcase end // // Byte 3 // always @(sel_byte3 or memdata) begin case(sel_byte3) `OR1200_M2R_ZERO: begin regdata_hh = 8'h00; end `OR1200_M2R_BYTE3: begin regdata_hh = memdata[31:24]; end `OR1200_M2R_EXTB0: begin regdata_hh = {{memdata[7]},{memdata[7]},{memdata[7]},{memdata[7]},{memdata[7]},{memdata[7]},{memdata[7]},{memdata[7]}}; end `OR1200_M2R_EXTB1: begin regdata_hh = {{memdata[15]},{memdata[15]},{memdata[15]},{memdata[15]},{memdata[15]},{memdata[15]},{memdata[15]},{memdata[15]}}; end `OR1200_M2R_EXTB2: begin regdata_hh = {{memdata[23]},{memdata[23]},{memdata[23]},{memdata[23]},{memdata[23]},{memdata[23]},{memdata[23]},{memdata[23]}}; end `OR1200_M2R_EXTB3: begin regdata_hh = {{memdata[31]},{memdata[31]},{memdata[31]},{memdata[31]},{memdata[31]},{memdata[31]},{memdata[31]},{memdata[31]}}; end endcase end // // Straightforward implementation of mem2reg // // reg [32-1:0] regdata; // // Alignment // always @(addr or memdata) begin case(addr) 2'b00: aligned = memdata; 2'b01: aligned = {memdata[23:0], 8'b00000000}; 2'b10: aligned = {memdata[15:0], 16'b0000000000000000}; 2'b11: aligned = {memdata[7:0], 24'b000000000000000000000000}; endcase end // // Bytes // /* always @(lsu_op or aligned) begin case(lsu_op) `OR1200_LSUOP_LBZ: begin regdata[7:0] = aligned[31:24]; regdata[31:8] = 24'b000000000000000000000000; end `OR1200_LSUOP_LBS: begin regdata[7:0] = aligned[31:24]; regdata[31:8] = {24'b000000000000000000000000}; end `OR1200_LSUOP_LHZ: begin regdata[15:0] = aligned[31:16]; regdata[31:16] = 16'b0000000000000000; end `OR1200_LSUOP_LHS: begin regdata[15:0] = aligned[31:16]; regdata[31:16] = {16'b0000000000000000}; end default: regdata = aligned; endcase end */ wire[8:0] unused_signal; assign unused_signal = lsu_op; endmodule //--------------------------------------- // A dual-port RAM // This module is tuned for VTR's benchmarks //--------------------------------------- module dual_port_ram ( input clk, input we1, input we2, input [`OR1200_REGFILE_ADDR_WIDTH - 1 : 0] addr1, input [`OR1200_OPERAND_WIDTH - 1 : 0] data1, output [`OR1200_OPERAND_WIDTH - 1 : 0] out1, input [`OR1200_REGFILE_ADDR_WIDTH - 1 : 0] addr2, input [`OR1200_OPERAND_WIDTH - 1 : 0] data2, output [`OR1200_OPERAND_WIDTH - 1 : 0] out2 ); reg [`OR1200_OPERAND_WIDTH - 1 : 0] ram[2**`OR1200_REGFILE_ADDR_WIDTH - 1 : 0]; reg [`OR1200_OPERAND_WIDTH - 1 : 0] data_out1; reg [`OR1200_OPERAND_WIDTH - 1 : 0] data_out2; assign out1 = data_out1; assign out2 = data_out2; // If writen enable 1 is activated, // data1 will be loaded through addr1 // Otherwise, data will be read out through addr1 always @(posedge clk) begin if (we1) begin ram[addr1] <= data1; end else begin data_out1 <= ram[addr1]; end end // If writen enable 2 is activated, // data1 will be loaded through addr2 // Otherwise, data will be read out through addr2 always @(posedge clk) begin if (we2) begin ram[addr2] <= data2; end else begin data_out2 <= ram[addr2]; end end endmodule