5283 lines
134 KiB
Verilog
Executable File
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
|