OpenFPGA/openfpga_flow/benchmarks/vtr_benchmark/or1200.v

5283 lines
134 KiB
Verilog
Executable File

`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