OpenCores
URL https://opencores.org/ocsvn/altor32/altor32/trunk

Subversion Repositories altor32

[/] [altor32/] [trunk/] [rtl/] [cpu/] [altor32_exec.v] - Diff between revs 27 and 31

Go to most recent revision | Show entire file | Details | Blame | View Log

Rev 27 Rev 31
Line 186... Line 186...
reg d_mem_load;
reg d_mem_load;
 
 
// Delayed NMI
// Delayed NMI
reg r_nmi;
reg r_nmi;
 
 
 
// SIM PUTC
 
`ifdef SIM_EXT_PUTC
 
    reg [7:0] r_putc;
 
`endif
 
 
//-----------------------------------------------------------------
//-----------------------------------------------------------------
// Instantiation
// Instantiation
//-----------------------------------------------------------------
//-----------------------------------------------------------------
 
 
// ALU
// ALU
Line 303... Line 308...
 
 
    // Stall due to failed resolve
    // Stall due to failed resolve
    .stall_o(resolve_failed)
    .stall_o(resolve_failed)
);
);
 
 
//-------------------------------------------------------------------
//-----------------------------------------------------------------
// Execute: Execute opcode
// Opcode decode
//-------------------------------------------------------------------
//-----------------------------------------------------------------
 
reg [7:0]  inst_r;
// Execute stage blocking assignment vars
reg [7:0]  alu_op_r;
reg [7:0] v_inst;
reg [1:0]  shift_op_r;
reg [4:0] v_rd;
reg [15:0] sfxx_op_r;
reg [7:0] v_alu_op;
reg [15:0] uint16_r;
reg [1:0] v_shift_op;
reg [31:0] uint32_r;
reg [15:0] v_sfxx_op;
reg [31:0] int32_r;
reg [15:0] v_imm;
reg [31:0] store_int32_r;
reg [31:0] v_imm_uint32;
reg [15:0] mxspr_uint16_r;
reg [31:0] v_imm_int32;
reg [31:0] target_int26_r;
reg [31:0] v_store_imm;
reg [31:0] reg_ra_r;
reg [15:0] v_mxspr_imm;
reg [31:0] reg_rb_r;
reg [31:0] v_target;
reg [31:0] shift_rb_r;
reg [31:0] v_reg_ra;
reg [31:0] shift_imm_r;
reg [31:0] v_reg_rb;
 
reg [31:0] v_pc;
always @ *
reg [31:0] v_offset;
begin
reg [31:0] v_shift_val;
    // Instruction
reg [31:0] v_shift_imm;
    inst_r               = {2'b00,opcode_i[31:26]};
reg [31:0] v_vector;
 
reg [31:0] v_sr;
    // Sub instructions
reg [31:0] v_mem_addr;
    alu_op_r             = {opcode_i[9:6],opcode_i[3:0]};
reg [31:0] v_mem_data_in;
    sfxx_op_r            = {5'b00,opcode_i[31:21]};
reg v_exception;
    shift_op_r           = opcode_i[7:6];
reg v_branch;
 
reg v_jmp;
 
reg v_write_rd;
 
reg v_store_pending;
 
reg v_load_pending;
 
reg v_inst_load;
 
reg v_inst_store;
 
reg v_stall;
 
reg v_no_intr;
 
reg v_opcode_valid;
 
reg v_check_load_rd;
 
 
 
always @ (posedge clk_i or posedge rst_i)
 
begin
 
   if (rst_i == 1'b1)
 
   begin
 
       r_pc_branch          <= 32'h00000000;
 
       r_pc_fetch           <= 1'b0;
 
       r_stall              <= 1'b0;
 
 
 
       // Status registers
    // Branch target
       r_epc                <= 32'h00000000;
    target_int26_r       = sign_extend_imm26(opcode_i[25:0]);
       r_sr                 <= 32'h00000000;
 
       r_esr                <= 32'h00000000;
 
 
 
       r_e_rd               <= 5'b00000;
    // Store immediate
 
    store_int32_r        = sign_extend_imm16({opcode_i[25:21],opcode_i[10:0]});
 
 
       // Default to no ALU operation
    // Signed & unsigned imm -> 32-bits
       r_e_alu_func         <= `ALU_NONE;
    uint16_r             = opcode_i[15:0];
       r_e_alu_a            <= 32'h00000000;
    int32_r              = sign_extend_imm16(opcode_i[15:0]);
       r_e_alu_b            <= 32'h00000000;
    uint32_r             = extend_imm16(opcode_i[15:0]);
 
 
 
    // Register values [ra/rb]
 
    reg_ra_r             = ra_value_resolved;
 
    reg_rb_r             = rb_value_resolved;
 
 
       r_e_opcode           <= 32'h00000000;
    // Shift ammount (from register[rb])
       r_e_opcode_pc        <= 32'h00000000;
    shift_rb_r           = {26'b00,rb_value_resolved[5:0]};
 
 
       // Data memory
    // Shift ammount (from immediate)
       dmem_addr_o          <= 32'h00000000;
    shift_imm_r          = {26'b00,opcode_i[5:0]};
       dmem_data_out_o      <= 32'h00000000;
 
       dmem_rd_o            <= 1'b0;
 
       dmem_wr_o            <= 4'b0000;
 
 
 
       fault_o              <= 1'b0;
    // MTSPR/MFSPR operand
       break_o              <= 1'b0;
    mxspr_uint16_r       = (ra_value_resolved[15:0] | {5'b00000,opcode_i[10:0]});
 
end
 
 
       r_nmi                <= 1'b0;
//-----------------------------------------------------------------
 
// Instruction Decode
 
//-----------------------------------------------------------------
 
wire inst_add_w     = (inst_r == `INST_OR32_ALU) & (alu_op_r == `INST_OR32_ADD);  // l.add
 
wire inst_addc_w    = (inst_r == `INST_OR32_ALU) & (alu_op_r == `INST_OR32_ADDC); // l.addc
 
wire inst_and_w     = (inst_r == `INST_OR32_ALU) & (alu_op_r == `INST_OR32_AND);  // l.and
 
wire inst_or_w      = (inst_r == `INST_OR32_ALU) & (alu_op_r == `INST_OR32_OR);   // l.or
 
wire inst_sll_w     = (inst_r == `INST_OR32_ALU) & (alu_op_r == `INST_OR32_SLL);  // l.sll
 
wire inst_sra_w     = (inst_r == `INST_OR32_ALU) & (alu_op_r == `INST_OR32_SRA);  // l.sra
 
wire inst_srl_w     = (inst_r == `INST_OR32_ALU) & (alu_op_r == `INST_OR32_SRL);  // l.srl
 
wire inst_sub_w     = (inst_r == `INST_OR32_ALU) & (alu_op_r == `INST_OR32_SUB);  // l.sub
 
wire inst_xor_w     = (inst_r == `INST_OR32_ALU) & (alu_op_r == `INST_OR32_XOR);  // l.xor
 
 
 
wire inst_addi_w    = (inst_r == `INST_OR32_ADDI);  // l.addi
 
wire inst_andi_w    = (inst_r == `INST_OR32_ANDI);  // l.andi
 
wire inst_bf_w      = (inst_r == `INST_OR32_BF);    // l.bf
 
wire inst_bnf_w     = (inst_r == `INST_OR32_BNF);   // l.bnf
 
wire inst_j_w       = (inst_r == `INST_OR32_J);     // l.j
 
wire inst_jal_w     = (inst_r == `INST_OR32_JAL);   // l.jal
 
wire inst_jalr_w    = (inst_r == `INST_OR32_JALR);  // l.jalr
 
wire inst_jr_w      = (inst_r == `INST_OR32_JR);    // l.jr
 
wire inst_lbs_w     = (inst_r == `INST_OR32_LBS);   // l.lbs
 
wire inst_lhs_w     = (inst_r == `INST_OR32_LHS);   // l.lhs
 
wire inst_lws_w     = (inst_r == `INST_OR32_LWS);   // l.lws
 
wire inst_lbz_w     = (inst_r == `INST_OR32_LBZ);   // l.lbz
 
wire inst_lhz_w     = (inst_r == `INST_OR32_LHZ);   // l.lhz
 
wire inst_lwz_w     = (inst_r == `INST_OR32_LWZ);   // l.lwz
 
wire inst_mfspr_w   = (inst_r == `INST_OR32_MFSPR); // l.mfspr
 
wire inst_mtspr_w   = (inst_r == `INST_OR32_MTSPR); // l.mtspr
 
wire inst_movhi_w   = (inst_r == `INST_OR32_MOVHI); // l.movhi
 
wire inst_nop_w     = (inst_r == `INST_OR32_NOP);   // l.nop
 
wire inst_ori_w     = (inst_r == `INST_OR32_ORI);   // l.ori
 
wire inst_rfe_w     = (inst_r == `INST_OR32_RFE);   // l.rfe
 
 
 
wire inst_sb_w      = (inst_r == `INST_OR32_SB);    // l.sb
 
wire inst_sh_w      = (inst_r == `INST_OR32_SH);    // l.sh
 
wire inst_sw_w      = (inst_r == `INST_OR32_SW);    // l.sw
 
 
 
wire inst_slli_w    = (inst_r == `INST_OR32_SHIFTI) & (shift_op_r == `INST_OR32_SLLI);  // l.slli
 
wire inst_srai_w    = (inst_r == `INST_OR32_SHIFTI) & (shift_op_r == `INST_OR32_SRAI);  // l.srai
 
wire inst_srli_w    = (inst_r == `INST_OR32_SHIFTI) & (shift_op_r == `INST_OR32_SRLI);  // l.srli
 
 
 
wire inst_xori_w    = (inst_r == `INST_OR32_XORI);   // l.xori
 
 
 
wire inst_sfxx_w    = (inst_r == `INST_OR32_SFXX);
 
wire inst_sfxxi_w   = (inst_r == `INST_OR32_SFXXI);
 
 
 
wire inst_sfeq_w    = (inst_r == `INST_OR32_SFXX) & (sfxx_op_r == `INST_OR32_SFEQ);   // l.sfeq
 
wire inst_sfges_w   = (inst_r == `INST_OR32_SFXX) & (sfxx_op_r == `INST_OR32_SFGES);  // l.sfges
 
 
 
wire inst_sfgeu_w   = (inst_r == `INST_OR32_SFXX) & (sfxx_op_r == `INST_OR32_SFGEU);  // l.sfgeu
 
wire inst_sfgts_w   = (inst_r == `INST_OR32_SFXX) & (sfxx_op_r == `INST_OR32_SFGTS);  // l.sfgts
 
wire inst_sfgtu_w   = (inst_r == `INST_OR32_SFXX) & (sfxx_op_r == `INST_OR32_SFGTU);  // l.sfgtu
 
wire inst_sfles_w   = (inst_r == `INST_OR32_SFXX) & (sfxx_op_r == `INST_OR32_SFLES);  // l.sfles
 
wire inst_sfleu_w   = (inst_r == `INST_OR32_SFXX) & (sfxx_op_r == `INST_OR32_SFLEU);  // l.sfleu
 
wire inst_sflts_w   = (inst_r == `INST_OR32_SFXX) & (sfxx_op_r == `INST_OR32_SFLTS);  // l.sflts
 
wire inst_sfltu_w   = (inst_r == `INST_OR32_SFXX) & (sfxx_op_r == `INST_OR32_SFLTU);  // l.sfltu
 
wire inst_sfne_w    = (inst_r == `INST_OR32_SFXX) & (sfxx_op_r == `INST_OR32_SFNE);   // l.sfne
 
 
 
wire inst_sfeqi_w   = (inst_r == `INST_OR32_SFXXI) & (sfxx_op_r == `INST_OR32_SFEQI);  // l.sfeqi
 
wire inst_sfgesi_w  = (inst_r == `INST_OR32_SFXXI) & (sfxx_op_r == `INST_OR32_SFGESI); // l.sfgesi
 
wire inst_sfgeui_w  = (inst_r == `INST_OR32_SFXXI) & (sfxx_op_r == `INST_OR32_SFGEUI); // l.sfgeui
 
wire inst_sfgtsi_w  = (inst_r == `INST_OR32_SFXXI) & (sfxx_op_r == `INST_OR32_SFGTSI); // l.sfgtsi
 
wire inst_sfgtui_w  = (inst_r == `INST_OR32_SFXXI) & (sfxx_op_r == `INST_OR32_SFGTUI); // l.sfgtui
 
wire inst_sflesi_w  = (inst_r == `INST_OR32_SFXXI) & (sfxx_op_r == `INST_OR32_SFLESI); // l.sflesi
 
 
 
wire inst_sfleui_w  = (inst_r == `INST_OR32_SFXXI) & (sfxx_op_r == `INST_OR32_SFLEUI); // l.sfleui
 
wire inst_sfltsi_w  = (inst_r == `INST_OR32_SFXXI) & (sfxx_op_r == `INST_OR32_SFLTSI); // l.sfltsi
 
wire inst_sfltui_w  = (inst_r == `INST_OR32_SFXXI) & (sfxx_op_r == `INST_OR32_SFLTUI); // l.sfltui
 
wire inst_sfnei_w   = (inst_r == `INST_OR32_SFXXI) & (sfxx_op_r == `INST_OR32_SFNEI);  // l.sfnei
 
 
       icache_flush_o       <= 1'b0;
wire inst_sys_w     = (inst_r == `INST_OR32_MISC) & (opcode_i[31:24] == `INST_OR32_SYS);  // l.sys
       dcache_flush_o       <= 1'b0;
wire inst_trap_w    = (inst_r == `INST_OR32_MISC) & (opcode_i[31:24] == `INST_OR32_TRAP); // l.trap
 
 
       r_mem_load           <= 1'b0;
//-----------------------------------------------------------------
       r_mem_store          <= 1'b0;
// Stall / Execute
       r_mem_access         <= 1'b0;
//-----------------------------------------------------------------
 
reg execute_inst_r;
 
reg stall_inst_r;
 
 
       r_load_rd            <= 5'b00000;
always @ *
       r_load_inst          <= 8'h00;
begin
       r_load_offset        <= 2'b00;
    execute_inst_r  = 1'b1;
 
    stall_inst_r    = 1'b0;
 
 
       d_mem_load           <= 1'b0;
    // No opcode ready or branch delay slot
 
    if (~opcode_valid_i | r_pc_fetch)
 
        execute_inst_r  = 1'b0;
 
    // Valid instruction, but load result / operand not ready
 
    else if (resolve_failed | load_stall)
 
        stall_inst_r    = 1'b1;
   end
   end
   else
 
   begin
 
 
 
       // If memory access accepted by slave
//-----------------------------------------------------------------
       if (dmem_accept_i)
// Next PC
 
//-----------------------------------------------------------------
 
reg [31:0]  next_pc_r;
 
 
 
always @ *
       begin
       begin
           dmem_rd_o            <= 1'b0;
    // Next expected PC (current PC + 4)
           dmem_wr_o            <= 4'b0000;
    next_pc_r  = (opcode_pc_i + 4);
       end
       end
 
 
       r_mem_access         <= 1'b0;
//-----------------------------------------------------------------
       break_o              <= 1'b0;
// Next SR
       icache_flush_o       <= 1'b0;
//-----------------------------------------------------------------
       dcache_flush_o       <= 1'b0;
reg [31:0]  next_sr_r;
 
reg         compare_result_r;
      // Record NMI in-case it can't be processed this cycle
always @ *
      if (nmi_i)
begin
          r_nmi <= 1'b1;
    next_sr_r = r_sr;
 
 
       // Reset branch request
    // Latch carry if updated
       r_pc_fetch           <= 1'b0;
    if (alu_carry_update)
 
        next_sr_r[`OR32_SR_CY] = alu_carry_out;
 
 
       v_exception          = 1'b0;
    // If valid instruction, check if SR needs updating
       v_vector             = 32'h00000000;
    if (execute_inst_r & ~stall_inst_r)
       v_branch             = 1'b0;
    begin
       v_jmp                = 1'b0;
      case (1'b1)
       v_write_rd           = 1'b0;
      inst_mtspr_w:
       v_sr                 = r_sr;
      begin
       v_stall              = 1'b0;
          case (mxspr_uint16_r)
       v_no_intr            = 1'b0;
          // SR - Supervision register
 
          `SPR_REG_SR:
 
          begin
 
              next_sr_r = reg_rb_r;
 
 
       d_mem_load          <= r_mem_access & r_mem_load;
              // Don't store cache flush requests
 
              next_sr_r[`OR32_SR_ICACHE_FLUSH] = 1'b0;
 
              next_sr_r[`OR32_SR_DCACHE_FLUSH] = 1'b0;
 
          end
 
          default:
 
            ;
 
          endcase
 
      end
 
      inst_rfe_w:
 
          next_sr_r = r_esr;
 
      inst_sfxx_w,
 
      inst_sfxxi_w:
 
           next_sr_r[`OR32_SR_F] = compare_result_r;
 
      default:
 
        ;
 
      endcase
 
    end
 
end
 
 
       //---------------------------------------------------------------
//-----------------------------------------------------------------
       // Opcode
// Next EPC/ESR
       //---------------------------------------------------------------   
//-----------------------------------------------------------------
 
reg [31:0]  next_epc_r;
 
reg [31:0]  next_esr_r;
 
 
       // Instruction not ready
always @ *
       if (!opcode_valid_i)
 
       begin
       begin
            v_opcode_valid  = 1'b0;
    next_epc_r = r_epc;
 
    next_esr_r = r_esr;
 
 
`ifdef CONF_CORE_DEBUG_BUBBLE
    case (1'b1)
            $display("%08x: Execute - Instruction not ready", opcode_pc_i);
    inst_mtspr_w: // l.mtspr
`endif
 
       end
 
       // Branch request, always drop the next instruction
 
       else if (r_pc_fetch)
 
       begin
       begin
            v_opcode_valid    = 1'b0;
       case (mxspr_uint16_r)
 
           // EPCR - EPC Exception saved PC
 
           `SPR_REG_EPCR:   next_epc_r = reg_rb_r;
 
 
`ifdef CONF_CORE_DEBUG
           // ESR - Exception saved SR
            $display("%08x: Exec - Branch pending, skip instruction (%x)", opcode_pc_i, opcode_i);
           `SPR_REG_ESR:    next_esr_r = reg_rb_r;
`endif
       endcase
       end
       end
       // Valid instruction ready     
    default:
       else
      ;
       begin
    endcase
            v_mem_data_in   = opcode_i;
 
            v_opcode_valid  = 1'b1;
 
 
 
`ifdef CONF_CORE_FAULT_ON_OPCODE0
 
            // This is a valid opcode (branch to same instruction), 
 
            // but rare and useful for catching pipeline errors
 
            if (v_mem_data_in == 32'h00000000)
 
                fault_o <= 1'b1;
 
`endif
 
       end
       end
 
 
       //---------------------------------------------------------------
//-----------------------------------------------------------------
       // Decode opcode
// ALU inputs
       //---------------------------------------------------------------          
//-----------------------------------------------------------------
       v_alu_op             = {v_mem_data_in[9:6],v_mem_data_in[3:0]};
 
       v_sfxx_op            = {5'b00,v_mem_data_in[31:21]};
 
       v_shift_op           = v_mem_data_in[7:6];
 
       v_target             = sign_extend_imm26(v_mem_data_in[25:0]);
 
       v_store_imm          = sign_extend_imm16({v_mem_data_in[25:21],v_mem_data_in[10:0]});
 
 
 
       // Signed & unsigned imm -> 32-bits
 
       v_imm                = v_mem_data_in[15:0];
 
       v_imm_int32          = sign_extend_imm16(v_imm);
 
       v_imm_uint32         = extend_imm16(v_imm);
 
 
 
       // Load register[ra]
 
       v_reg_ra             = ra_value_resolved;
 
 
 
       // Load register[rb]
 
       v_reg_rb             = rb_value_resolved;
 
 
 
       // Default to no ALU operation (output == input_a)
// ALU operation selection
       r_e_alu_func         <= `ALU_NONE;
reg [3:0]  alu_func_r;
       r_e_alu_a            <= 32'h00000000;
 
 
 
       // Default target is R[d]
// ALU operands
       v_rd                 = reg_rd_i;
reg [31:0] alu_input_a_r;
 
reg [31:0] alu_input_b_r;
 
reg        write_rd_r;
 
 
       //---------------------------------------------------------------
always @ *
       // Outstanding memory access
begin
       //--------------------------------------------------------------- 
   alu_func_r     = `ALU_NONE;
 
   alu_input_a_r  = 32'b0;
 
   alu_input_b_r  = 32'b0;
 
   write_rd_r     = 1'b0;
 
 
       // Pending accesses
   case (1'b1)
       v_load_pending   = load_pending;
 
       v_store_pending  = store_pending;
 
       v_check_load_rd  = 1'b1;
 
 
 
       // Stall pipeline due to load / store
     inst_add_w: // l.add
       if (v_opcode_valid & load_stall)
 
       begin
       begin
           v_stall        = 1'b1;
       alu_func_r     = `ALU_ADD;
           v_opcode_valid = 1'b0;
       alu_input_a_r  = reg_ra_r;
 
       alu_input_b_r  = reg_rb_r;
 
       write_rd_r     = 1'b1;
       end
       end
 
 
       // Insert load result into pipeline?
     inst_addc_w: // l.addc
       if (load_insert)
 
       begin
       begin
           // Feed load result into pipeline
         alu_func_r     = `ALU_ADDC;
           r_e_alu_func         <= `ALU_NONE;
         alu_input_a_r  = reg_ra_r;
           r_e_alu_a            <= load_result;
         alu_input_b_r  = reg_rb_r;
           v_rd                  = r_load_rd;
         write_rd_r     = 1'b1;
           v_write_rd            = 1'b1;
 
       end
       end
 
 
       //---------------------------------------------------------------
     inst_and_w: // l.and
       // Invalid PC detection
 
       //---------------------------------------------------------------
 
 
 
       // Detect incorrect program counter and cause FAULT
 
       if (opcode_valid_i && (opcode_pc_i[1:0] != 2'b00))
 
       begin
       begin
            fault_o        <= 1'b1;
         alu_func_r     = `ALU_AND;
            v_opcode_valid  = 1'b0;
         alu_input_a_r  = reg_ra_r;
            v_exception     = 1'b1;
         alu_input_b_r  = reg_rb_r;
            v_vector        = ISR_VECTOR + `VECTOR_BUS_ERROR;
         write_rd_r     = 1'b1;
       end
       end
 
 
       //---------------------------------------------------------------
     inst_or_w: // l.or
       // Failed operand resolve?
 
       //---------------------------------------------------------------
 
       if (opcode_valid_i & resolve_failed)
 
       begin
       begin
`ifdef CONF_CORE_DEBUG
         alu_func_r     = `ALU_OR;
            $display("%08x: Operand resolve failed RA=%d, RB=%d", opcode_pc_i, reg_ra_i, reg_rb_i);
         alu_input_a_r  = reg_ra_r;
`endif
         alu_input_b_r  = reg_rb_r;
            // Stall!
         write_rd_r     = 1'b1;
            v_opcode_valid  = 1'b0;
 
            v_stall         = 1'b1;
 
       end
       end
 
 
       //---------------------------------------------------------------
     inst_sll_w: // l.sll
       // Final instruction decoding
 
       //--------------------------------------------------------------- 
 
 
 
       // Insert bubble into the pipeline?
 
       if (!v_opcode_valid)
 
       begin
       begin
            v_mem_data_in   = `OPCODE_INST_BUBBLE;
         alu_func_r     = `ALU_SHIFTL;
            v_check_load_rd = 1'b0;
         alu_input_a_r  = reg_ra_r;
 
         alu_input_b_r  = shift_rb_r;
 
         write_rd_r     = 1'b1;
       end
       end
 
 
       // Store opcode (after possible bubble generation)
     inst_sra_w: // l.sra
       r_e_opcode            <= v_mem_data_in;
 
       r_e_opcode_pc         <= opcode_pc_i;
 
 
 
       // Decode instruction
 
       v_inst               = {2'b00,v_mem_data_in[31:26]};
 
 
 
       // Shift ammount (from register[rb])
 
       v_shift_val          = {26'b00,v_reg_rb[5:0]};
 
 
 
       // Shift ammount (from immediate)
 
       v_shift_imm          = {26'b00,v_imm[5:0]};
 
 
 
       // MTSPR/MFSPR operand
 
       v_mxspr_imm          =  (v_reg_ra[15:0] | {5'b00000,v_mem_data_in[10:0]});
 
 
 
       // Next expected PC (current PC + 4)
 
       v_pc                 = (opcode_pc_i + 4);
 
 
 
       // Latch carry if updated
 
       if (alu_carry_update)
 
            v_sr[`OR32_SR_CY] = alu_carry_out;
 
 
 
`ifdef CONF_CORE_TRACE
 
       if (v_opcode_valid)
 
       begin
       begin
            $display("%08x: Execute 0x%08x", opcode_pc_i, v_mem_data_in);
         alu_func_r     = `ALU_SHIRTR_ARITH;
            $display(" rA[%d] = 0x%08x", reg_ra_i, v_reg_ra);
         alu_input_a_r  = reg_ra_r;
            $display(" rB[%d] = 0x%08x", reg_rb_i, v_reg_rb);
         alu_input_b_r  = shift_rb_r;
 
         write_rd_r     = 1'b1;
       end
       end
`endif
 
 
 
       //---------------------------------------------------------------
     inst_srl_w: // l.srl
       // Execute instruction
 
       //---------------------------------------------------------------
 
       case (v_inst)
 
           `INST_OR32_BUBBLE :
 
           begin
 
                // Do not allow external interrupts whilst executing a bubble
 
                // as this will result in pipeline issues.
 
                v_no_intr = 1'b1;
 
           end
 
           `INST_OR32_ALU :
 
           begin
 
               case (v_alu_op)
 
                   `INST_OR32_ADD: // l.add
 
                   begin
                   begin
                       r_e_alu_func <= `ALU_ADD;
         alu_func_r     = `ALU_SHIFTR;
                       r_e_alu_a <= v_reg_ra;
         alu_input_a_r  = reg_ra_r;
                       r_e_alu_b <= v_reg_rb;
         alu_input_b_r  = shift_rb_r;
                       v_write_rd = 1'b1;
         write_rd_r     = 1'b1;
                   end
                   end
 
 
                   `INST_OR32_ADDC: // l.addc
     inst_sub_w: // l.sub
                   begin
                   begin
                       r_e_alu_func <= `ALU_ADDC;
         alu_func_r     = `ALU_SUB;
                       r_e_alu_a <= v_reg_ra;
         alu_input_a_r  = reg_ra_r;
                       r_e_alu_b <= v_reg_rb;
         alu_input_b_r  = reg_rb_r;
                       v_write_rd = 1'b1;
         write_rd_r     = 1'b1;
                   end
                   end
 
 
                   `INST_OR32_AND: // l.and
     inst_xor_w: // l.xor
                   begin
                   begin
                       r_e_alu_func <= `ALU_AND;
         alu_func_r     = `ALU_XOR;
                       r_e_alu_a <= v_reg_ra;
         alu_input_a_r  = reg_ra_r;
                       r_e_alu_b <= v_reg_rb;
         alu_input_b_r  = reg_rb_r;
                       v_write_rd = 1'b1;
         write_rd_r     = 1'b1;
                   end
                   end
 
 
                   `INST_OR32_OR: // l.or
     inst_addi_w: // l.addi
                   begin
                   begin
                       r_e_alu_func <= `ALU_OR;
         alu_func_r     = `ALU_ADD;
                       r_e_alu_a <= v_reg_ra;
         alu_input_a_r  = reg_ra_r;
                       r_e_alu_b <= v_reg_rb;
         alu_input_b_r  = int32_r;
                       v_write_rd = 1'b1;
         write_rd_r     = 1'b1;
                   end
                   end
 
 
                   `INST_OR32_SLL: // l.sll
     inst_andi_w: // l.andi
                   begin
                   begin
                       r_e_alu_func <= `ALU_SHIFTL;
         alu_func_r     = `ALU_AND;
                       r_e_alu_a <= v_reg_ra;
         alu_input_a_r  = reg_ra_r;
                       r_e_alu_b <= v_shift_val;
         alu_input_b_r  = uint32_r;
                       v_write_rd = 1'b1;
         write_rd_r     = 1'b1;
                   end
                   end
 
 
                   `INST_OR32_SRA: // l.sra
     inst_jal_w: // l.jal
                   begin
                   begin
                       r_e_alu_func <= `ALU_SHIRTR_ARITH;
         alu_input_a_r  = next_pc_r;
                       r_e_alu_a <= v_reg_ra;
         write_rd_r     = 1'b1;
                       r_e_alu_b <= v_shift_val;
 
                       v_write_rd = 1'b1;
 
                   end
                   end
 
 
                   `INST_OR32_SRL: // l.srl
     inst_jalr_w: // l.jalr
                   begin
                   begin
                       r_e_alu_func <= `ALU_SHIFTR;
         alu_input_a_r  = next_pc_r;
                       r_e_alu_a <= v_reg_ra;
         write_rd_r     = 1'b1;
                       r_e_alu_b <= v_shift_val;
 
                       v_write_rd = 1'b1;
 
                   end
                   end
 
 
                   `INST_OR32_SUB: // l.sub
     inst_mfspr_w: // l.mfspr
 
     begin
 
        case (mxspr_uint16_r)
 
           // SR - Supervision register
 
           `SPR_REG_SR:
                   begin
                   begin
                       r_e_alu_func <= `ALU_SUB;
               alu_input_a_r = next_sr_r;
                       r_e_alu_a <= v_reg_ra;
               write_rd_r    = 1'b1;
                       r_e_alu_b <= v_reg_rb;
 
                       v_write_rd = 1'b1;
 
                   end
                   end
 
 
                   `INST_OR32_XOR: // l.xor
           // EPCR - EPC Exception saved PC
 
           `SPR_REG_EPCR:
                   begin
                   begin
                       r_e_alu_func <= `ALU_XOR;
               alu_input_a_r  = r_epc;
                       r_e_alu_a <= v_reg_ra;
               write_rd_r     = 1'b1;
                       r_e_alu_b <= v_reg_rb;
 
                       v_write_rd = 1'b1;
 
                   end
                   end
 
 
                   default:
           // ESR - Exception saved SR
 
           `SPR_REG_ESR:
                   begin
                   begin
                       fault_o <= 1'b1;
               alu_input_a_r  = r_esr;
                       v_exception = 1'b1;
               write_rd_r     = 1'b1;
                       v_vector = ISR_VECTOR + `VECTOR_ILLEGAL_INST;
 
                   end
                   end
 
           default:
 
              ;
               endcase
               endcase
           end
           end
 
 
           `INST_OR32_ADDI: // l.addi
     inst_movhi_w: // l.movhi
           begin
           begin
               r_e_alu_func <= `ALU_ADD;
         alu_input_a_r  = {uint16_r,16'h0000};
               r_e_alu_a <= v_reg_ra;
         write_rd_r     = 1'b1;
               r_e_alu_b <= v_imm_int32;
 
               v_write_rd = 1'b1;
 
           end
           end
 
 
           `INST_OR32_ANDI: // l.andi
     inst_ori_w: // l.ori
           begin
           begin
               r_e_alu_func <= `ALU_AND;
         alu_func_r     = `ALU_OR;
               r_e_alu_a <= v_reg_ra;
         alu_input_a_r  = reg_ra_r;
               r_e_alu_b <= v_imm_uint32;
         alu_input_b_r  = uint32_r;
               v_write_rd = 1'b1;
         write_rd_r     = 1'b1;
           end
           end
 
 
           `INST_OR32_BF: // l.bf
     inst_slli_w: // l.slli
           begin
           begin
               if (v_sr[`OR32_SR_F] == 1'b1)
         alu_func_r     = `ALU_SHIFTL;
                    v_branch = 1'b1;
         alu_input_a_r  = reg_ra_r;
 
         alu_input_b_r  = shift_imm_r;
 
         write_rd_r     = 1'b1;
           end
           end
 
 
           `INST_OR32_BNF: // l.bnf
     inst_srai_w: // l.srai
           begin
           begin
               if (v_sr[`OR32_SR_F] == 1'b0)
         alu_func_r     = `ALU_SHIRTR_ARITH;
                    v_branch = 1'b1;
         alu_input_a_r  = reg_ra_r;
 
         alu_input_b_r  = shift_imm_r;
 
         write_rd_r     = 1'b1;
           end
           end
 
 
           `INST_OR32_J: // l.j
     inst_srli_w: // l.srli
           begin
           begin
               v_branch = 1'b1;
         alu_func_r     = `ALU_SHIFTR;
 
         alu_input_a_r  = reg_ra_r;
 
         alu_input_b_r  = shift_imm_r;
 
         write_rd_r     = 1'b1;
           end
           end
 
 
           `INST_OR32_JAL: // l.jal
     // l.lbs l.lhs l.lws l.lbz l.lhz l.lwz
           begin
     inst_lbs_w,
               r_e_alu_a <= v_pc;
     inst_lhs_w,
               v_write_rd = 1'b1;
     inst_lws_w,
               v_rd       = 5'b01001; // Write to REG_9_LR
     inst_lbz_w,
`ifdef CONF_CORE_DEBUG
     inst_lhz_w,
               $display(" Save 0x%x to LR", v_pc);
     inst_lwz_w:
`endif
          write_rd_r    = 1'b1;
               v_branch = 1'b1;
 
 
     inst_xori_w: // l.xori
 
     begin
 
         alu_func_r     = `ALU_XOR;
 
         alu_input_a_r  = reg_ra_r;
 
         alu_input_b_r  = int32_r;
 
         write_rd_r     = 1'b1;
 
     end
 
     default:
 
        ;
 
   endcase
           end
           end
 
 
          `INST_OR32_JALR: // l.jalr
//-----------------------------------------------------------------
 
// Comparisons
 
//-----------------------------------------------------------------
 
always @ *
           begin
           begin
               r_e_alu_a <= v_pc;
    compare_result_r = 1'b0;
               v_write_rd = 1'b1;
 
               v_rd       = 5'b01001; // Write to REG_9_LR
 
`ifdef CONF_CORE_DEBUG
 
               $display(" Save 0x%x to LR", v_pc);
 
`endif
 
               v_pc = v_reg_rb;
 
               v_jmp = 1;
 
           end
 
 
 
          `INST_OR32_JR: // l.jr
    case (1'b1)
 
    inst_sfeq_w: // l.sfeq
           begin
           begin
               v_pc = v_reg_rb;
        if (reg_ra_r == reg_rb_r)
               v_jmp = 1;
            compare_result_r = 1'b1;
 
        else
 
            compare_result_r = 1'b0;
           end
           end
 
 
           // l.lbs l.lhs l.lws l.lbz l.lhz l.lwz
    inst_sfeqi_w: // l.sfeqi
           `INST_OR32_LBS, `INST_OR32_LHS, `INST_OR32_LWS, `INST_OR32_LBZ, `INST_OR32_LHZ, `INST_OR32_LWZ :
 
           begin
           begin
               v_mem_addr = (v_reg_ra + v_imm_int32);
        if (reg_ra_r == int32_r)
               dmem_addr_o <= v_mem_addr;
            compare_result_r = 1'b1;
               dmem_data_out_o <= 32'h00000000;
        else
               dmem_rd_o <= 1'b1;
            compare_result_r = 1'b0;
 
    end
               // Writeback if load result ready
 
               v_write_rd = 1'b1;
 
               v_check_load_rd = 1'b0;
 
 
 
               // Mark load as pending
 
               v_load_pending   = 1'b1;
 
               r_mem_access    <= 1'b1;
 
 
 
               // Record target register
 
               r_load_rd    <= reg_rd_i;
 
               r_load_inst  <= v_inst;
 
               r_load_offset<= v_mem_addr[1:0];
 
 
 
`ifdef CONF_CORE_DEBUG
    inst_sfges_w: // l.sfges
               $display(" Load from 0x%08x to R%d", v_mem_addr, reg_rd_i);
 
`endif
 
                // Detect bad load address & fault (ignore bit 31)
 
                if (v_mem_addr[30:28] != 3'h1)
 
                begin
                begin
                    v_load_pending  = 1'b0;
        if (greater_than_equal_signed(reg_ra_r, reg_rb_r) == 1'b1)
                    dmem_rd_o      <= 1'b0;
            compare_result_r = 1'b1;
                    r_mem_access   <= 1'b0;
        else
                    fault_o        <= 1'b1;
            compare_result_r = 1'b0;
                    v_exception     = 1'b1;
 
                    v_vector        = ISR_VECTOR + `VECTOR_BUS_ERROR;
 
                end
 
           end
           end
 
 
          `INST_OR32_MFSPR: // l.mfspr
    inst_sfgesi_w: // l.sfgesi
          begin
          begin
               case (v_mxspr_imm)
        if (greater_than_equal_signed(reg_ra_r, int32_r) == 1'b1)
                   // SR - Supervision register
            compare_result_r = 1'b1;
                   `SPR_REG_SR:
        else
                   begin
            compare_result_r = 1'b0;
                       r_e_alu_a <= v_sr;
 
                       v_write_rd = 1'b1;
 
                   end
                   end
 
 
                   // EPCR - EPC Exception saved PC
    inst_sfgeu_w: // l.sfgeu
                   `SPR_REG_EPCR:
 
                   begin
                   begin
                       r_e_alu_a <= r_epc;
        if (reg_ra_r >= reg_rb_r)
                       v_write_rd = 1'b1;
            compare_result_r = 1'b1;
 
        else
 
            compare_result_r = 1'b0;
                   end
                   end
 
 
                   // ESR - Exception saved SR
    inst_sfgeui_w: // l.sfgeui
                   `SPR_REG_ESR:
 
                   begin
                   begin
                       r_e_alu_a <= r_esr;
        if (reg_ra_r >= int32_r)
                       v_write_rd = 1'b1;
            compare_result_r = 1'b1;
 
        else
 
            compare_result_r = 1'b0;
                   end
                   end
 
 
                   default:
    inst_sfgts_w: // l.sfgts
                   begin
                   begin
                       fault_o <= 1'b1;
        if (greater_than_signed(reg_ra_r, reg_rb_r) == 1'b1)
                       v_exception = 1'b1;
            compare_result_r = 1'b1;
                       v_vector = ISR_VECTOR + `VECTOR_ILLEGAL_INST;
        else
                   end
            compare_result_r = 1'b0;
               endcase
 
           end
           end
 
 
          `INST_OR32_MTSPR: // l.mtspr
    inst_sfgtsi_w: // l.sfgtsi
          begin
 
               case (v_mxspr_imm)
 
                   // SR - Supervision register
 
                   `SPR_REG_SR:
 
                   begin
                   begin
                       v_sr = v_reg_rb;
        if (greater_than_signed(reg_ra_r, int32_r) == 1'b1)
 
            compare_result_r = 1'b1;
                       // Cache flush request?
        else
                       icache_flush_o <= v_reg_rb[`OR32_SR_ICACHE_FLUSH];
            compare_result_r = 1'b0;
                       dcache_flush_o <= v_reg_rb[`OR32_SR_DCACHE_FLUSH];
 
 
 
                       // Don't store cache flush requests
 
                       v_sr[`OR32_SR_ICACHE_FLUSH] = 1'b0;
 
                       v_sr[`OR32_SR_DCACHE_FLUSH] = 1'b0;
 
                   end
                   end
 
 
                   // EPCR - EPC Exception saved PC
    inst_sfgtu_w: // l.sfgtu
                   `SPR_REG_EPCR:
 
                   begin
                   begin
                       r_epc <= v_reg_rb;
        if (reg_ra_r > reg_rb_r)
 
            compare_result_r = 1'b1;
 
        else
 
            compare_result_r = 1'b0;
                   end
                   end
 
 
                   // ESR - Exception saved SR
    inst_sfgtui_w: // l.sfgtui
                   `SPR_REG_ESR:
 
                   begin
                   begin
                       r_esr <= v_reg_rb;
        if (reg_ra_r > int32_r)
 
            compare_result_r = 1'b1;
 
        else
 
            compare_result_r = 1'b0;
                   end
                   end
 
 
                   default:
    inst_sfles_w: // l.sfles
                   begin
                   begin
                       fault_o <= 1'b1;
        if (less_than_equal_signed(reg_ra_r, reg_rb_r) == 1'b1)
                       v_exception = 1'b1;
            compare_result_r = 1'b1;
                       v_vector = ISR_VECTOR + `VECTOR_ILLEGAL_INST;
        else
                   end
            compare_result_r = 1'b0;
               endcase
 
           end
           end
 
 
           `INST_OR32_MOVHI: // l.movhi
    inst_sflesi_w: // l.sflesi
           begin
           begin
               r_e_alu_a <= {v_imm,16'h0000};
        if (less_than_equal_signed(reg_ra_r, int32_r) == 1'b1)
               v_write_rd = 1'b1;
            compare_result_r = 1'b1;
 
        else
 
            compare_result_r = 1'b0;
           end
           end
 
 
           `INST_OR32_NOP: // l.nop
    inst_sfleu_w: // l.sfleu
           begin
           begin
              `ifdef SIMULATION
        if (reg_ra_r <= reg_rb_r)
              case (v_imm)
            compare_result_r = 1'b1;
              // NOP_PUTC
        else
              16'h0004:  $write("%c", v_reg_ra[7:0]);
            compare_result_r = 1'b0;
              // NOP
 
              16'h0000: ;
 
              endcase
 
              `endif
 
           end
           end
 
 
           `INST_OR32_ORI: // l.ori
    inst_sfleui_w: // l.sfleui
           begin
           begin
               r_e_alu_func <= `ALU_OR;
        if (reg_ra_r <= int32_r)
               r_e_alu_a <= v_reg_ra;
            compare_result_r = 1'b1;
               r_e_alu_b <= v_imm_uint32;
        else
               v_write_rd = 1'b1;
            compare_result_r = 1'b0;
           end
           end
 
 
           `INST_OR32_RFE: // l.rfe
    inst_sflts_w: // l.sflts
           begin
           begin
                v_pc      = r_epc;
        if (less_than_signed(reg_ra_r, reg_rb_r) == 1'b1)
                v_sr      = r_esr;
            compare_result_r = 1'b1;
                v_jmp     = 1;
        else
 
            compare_result_r = 1'b0;
           end
           end
 
 
          `INST_OR32_SHIFTI :
    inst_sfltsi_w: // l.sfltsi
          begin
          begin
               case (v_shift_op)
        if (less_than_signed(reg_ra_r, int32_r) == 1'b1)
                   `INST_OR32_SLLI: // l.slli
            compare_result_r = 1'b1;
                   begin
        else
                       r_e_alu_func <= `ALU_SHIFTL;
            compare_result_r = 1'b0;
                       r_e_alu_a <= v_reg_ra;
 
                       r_e_alu_b <= v_shift_imm;
 
                       v_write_rd = 1'b1;
 
                   end
                   end
 
 
                   `INST_OR32_SRAI: // l.srai
    inst_sfltu_w: // l.sfltu
                   begin
                   begin
                       r_e_alu_func <= `ALU_SHIRTR_ARITH;
        if (reg_ra_r < reg_rb_r)
                       r_e_alu_a <= v_reg_ra;
            compare_result_r = 1'b1;
                       r_e_alu_b <= v_shift_imm;
        else
                       v_write_rd = 1'b1;
            compare_result_r = 1'b0;
                   end
                   end
 
 
                   `INST_OR32_SRLI: // l.srli
    inst_sfltui_w: // l.sfltui
                     begin
                     begin
                       r_e_alu_func <= `ALU_SHIFTR;
        if (reg_ra_r < int32_r)
                       r_e_alu_a <= v_reg_ra;
            compare_result_r = 1'b1;
                       r_e_alu_b <= v_shift_imm;
        else
                       v_write_rd = 1'b1;
            compare_result_r = 1'b0;
                   end
                   end
 
 
                   default:
    inst_sfne_w: // l.sfne
                   begin
                   begin
                       fault_o <= 1'b1;
        if (reg_ra_r != reg_rb_r)
                       v_exception = 1'b1;
            compare_result_r = 1'b1;
                       v_vector = ISR_VECTOR + `VECTOR_ILLEGAL_INST;
        else
                   end
            compare_result_r = 1'b0;
               endcase
 
           end
           end
 
 
           `INST_OR32_SB:
    inst_sfnei_w: // l.sfnei
           begin
 
               v_mem_addr = (v_reg_ra + v_store_imm);
 
               dmem_addr_o <= v_mem_addr;
 
               r_mem_access <= 1'b1;
 
               case (v_mem_addr[1:0])
 
                   2'b00 :
 
                   begin
 
                       dmem_data_out_o <= {v_reg_rb[7:0],24'h000000};
 
                       dmem_wr_o <= 4'b1000;
 
                       v_store_pending  = 1'b1;
 
                   end
 
                   2'b01 :
 
                   begin
 
                       dmem_data_out_o <= {{8'h00,v_reg_rb[7:0]},16'h0000};
 
                       dmem_wr_o <= 4'b0100;
 
                       v_store_pending  = 1'b1;
 
                   end
 
                   2'b10 :
 
                   begin
                   begin
                       dmem_data_out_o <= {{16'h0000,v_reg_rb[7:0]},8'h00};
        if (reg_ra_r != int32_r)
                       dmem_wr_o <= 4'b0010;
            compare_result_r = 1'b1;
                       v_store_pending  = 1'b1;
        else
                   end
            compare_result_r = 1'b0;
                   2'b11 :
 
                   begin
 
                       dmem_data_out_o <= {24'h000000,v_reg_rb[7:0]};
 
                       dmem_wr_o <= 4'b0001;
 
                       v_store_pending  = 1'b1;
 
                   end
                   end
                   default :
                   default :
                   begin
        ;
                       dmem_data_out_o <= 32'h00000000;
 
                       dmem_wr_o <= 4'b0000;
 
                   end
 
               endcase
               endcase
           end
           end
 
 
          `INST_OR32_SFXX, `INST_OR32_SFXXI:
//-----------------------------------------------------------------
          begin
// Load/Store operation?
               case (v_sfxx_op)
//-----------------------------------------------------------------
                   `INST_OR32_SFEQ: // l.sfeq
reg         load_inst_r;
                   begin
reg         store_inst_r;
                        if (v_reg_ra == v_reg_rb)
reg [31:0]  mem_addr_r;
                            v_sr[`OR32_SR_F] = 1'b1;
always @ *
                        else
begin
                            v_sr[`OR32_SR_F] = 1'b0;
    load_inst_r  = inst_lbs_w | inst_lhs_w | inst_lws_w |
                   end
                   inst_lbz_w | inst_lhz_w | inst_lwz_w;
 
    store_inst_r = inst_sb_w  | inst_sh_w  | inst_sw_w;
 
 
                   `INST_OR32_SFEQI: // l.sfeqi
    // Memory address is relative to RA
                   begin
    mem_addr_r = reg_ra_r + (store_inst_r ? store_int32_r : int32_r);
                        if (v_reg_ra == v_imm_int32)
 
                            v_sr[`OR32_SR_F] = 1'b1;
 
                        else
 
                            v_sr[`OR32_SR_F] = 1'b0;
 
                   end
                   end
 
 
                   `INST_OR32_SFGES: // l.sfges
//-----------------------------------------------------------------
                   begin
// Branches
                        if (greater_than_equal_signed(v_reg_ra, v_reg_rb) == 1'b1)
//-----------------------------------------------------------------
                            v_sr[`OR32_SR_F] = 1'b1;
reg         branch_r;
                        else
reg         branch_link_r;
                            v_sr[`OR32_SR_F] = 1'b0;
reg [31:0]  branch_target_r;
                   end
reg         branch_except_r;
 
 
                   `INST_OR32_SFGESI: // l.sfgesi
always @ *
                   begin
                   begin
                        if (greater_than_equal_signed(v_reg_ra, v_imm_int32) == 1'b1)
 
                            v_sr[`OR32_SR_F] = 1'b1;
 
                        else
 
                            v_sr[`OR32_SR_F] = 1'b0;
 
                   end
 
 
 
                   `INST_OR32_SFGEU: // l.sfgeu
    branch_r        = 1'b0;
                   begin
    branch_link_r   = 1'b0;
                        if (v_reg_ra >= v_reg_rb)
    branch_except_r = 1'b0;
                            v_sr[`OR32_SR_F] = 1'b1;
 
                        else
 
                            v_sr[`OR32_SR_F] = 1'b0;
 
                   end
 
 
 
                   `INST_OR32_SFGEUI: // l.sfgeui
    // Default branch target is relative to current PC
                   begin
    branch_target_r = (opcode_pc_i + {target_int26_r[29:0],2'b00});
                        if (v_reg_ra >= v_imm_int32)
 
                            v_sr[`OR32_SR_F] = 1'b1;
 
                        else
 
                            v_sr[`OR32_SR_F] = 1'b0;
 
                   end
 
 
 
                   `INST_OR32_SFGTS: // l.sfgts
    case (1'b1)
                   begin
    inst_bf_w: // l.bf
                        if (greater_than_signed(v_reg_ra, v_reg_rb) == 1'b1)
        branch_r      = r_sr[`OR32_SR_F];
                            v_sr[`OR32_SR_F] = 1'b1;
 
                        else
 
                            v_sr[`OR32_SR_F] = 1'b0;
 
                   end
 
 
 
                   `INST_OR32_SFGTSI: // l.sfgtsi
    inst_bnf_w: // l.bnf
                   begin
        branch_r      = ~r_sr[`OR32_SR_F];
                        if (greater_than_signed(v_reg_ra, v_imm_int32) == 1'b1)
 
                            v_sr[`OR32_SR_F] = 1'b1;
 
                        else
 
                            v_sr[`OR32_SR_F] = 1'b0;
 
                   end
 
 
 
                   `INST_OR32_SFGTU: // l.sfgtu
    inst_j_w: // l.j
                   begin
        branch_r      = 1'b1;
                        if (v_reg_ra > v_reg_rb)
 
                            v_sr[`OR32_SR_F] = 1'b1;
 
                        else
 
                            v_sr[`OR32_SR_F] = 1'b0;
 
                   end
 
 
 
                   `INST_OR32_SFGTUI: // l.sfgtui
    inst_jal_w: // l.jal
                   begin
                   begin
                        if (v_reg_ra > v_imm_int32)
        // Write to REG_9_LR
                            v_sr[`OR32_SR_F] = 1'b1;
        branch_link_r = 1'b1;
                        else
        branch_r      = 1'b1;
                            v_sr[`OR32_SR_F] = 1'b0;
 
                   end
                   end
 
 
                   `INST_OR32_SFLES: // l.sfles
    inst_jalr_w: // l.jalr
                   begin
                   begin
                        if (less_than_equal_signed(v_reg_ra, v_reg_rb) == 1'b1)
        // Write to REG_9_LR
                            v_sr[`OR32_SR_F] = 1'b1;
        branch_link_r   = 1'b1;
                        else
        branch_r        = 1'b1;
                            v_sr[`OR32_SR_F] = 1'b0;
        branch_target_r = reg_rb_r;
                   end
                   end
 
 
                   `INST_OR32_SFLESI: // l.sflesi
    inst_jr_w: // l.jr
                   begin
                   begin
                        if (less_than_equal_signed(v_reg_ra, v_imm_int32) == 1'b1)
        branch_r        = 1'b1;
                            v_sr[`OR32_SR_F] = 1'b1;
        branch_target_r = reg_rb_r;
                        else
 
                            v_sr[`OR32_SR_F] = 1'b0;
 
                   end
                   end
 
 
                   `INST_OR32_SFLEU: // l.sfleu
    inst_rfe_w: // l.rfe
                   begin
                   begin
                        if (v_reg_ra <= v_reg_rb)
        branch_r        = 1'b1;
                            v_sr[`OR32_SR_F] = 1'b1;
        branch_target_r = r_epc;
                        else
 
                            v_sr[`OR32_SR_F] = 1'b0;
 
                   end
                   end
 
 
                   `INST_OR32_SFLEUI: // l.sfleui
    inst_sys_w: // l.sys
                   begin
                   begin
                        if (v_reg_ra <= v_imm_int32)
        branch_r        = 1'b1;
                            v_sr[`OR32_SR_F] = 1'b1;
        branch_except_r = 1'b1;
                        else
        branch_target_r = ISR_VECTOR + `VECTOR_SYSCALL;
                            v_sr[`OR32_SR_F] = 1'b0;
 
                   end
                   end
 
 
                   `INST_OR32_SFLTS: // l.sflts
    inst_trap_w: // l.trap
                   begin
                   begin
                        if (less_than_signed(v_reg_ra, v_reg_rb) == 1'b1)
        branch_r        = 1'b1;
                            v_sr[`OR32_SR_F] = 1'b1;
        branch_except_r = 1'b1;
                        else
        branch_target_r = ISR_VECTOR + `VECTOR_TRAP;
                            v_sr[`OR32_SR_F] = 1'b0;
 
                   end
                   end
 
 
                   `INST_OR32_SFLTSI: // l.sfltsi
    default:
                   begin
        ;
                        if (less_than_signed(v_reg_ra, v_imm_int32) == 1'b1)
    endcase
                            v_sr[`OR32_SR_F] = 1'b1;
 
                        else
 
                            v_sr[`OR32_SR_F] = 1'b0;
 
                   end
                   end
 
 
                   `INST_OR32_SFLTU: // l.sfltu
//-----------------------------------------------------------------
 
// Invalid instruction
 
//-----------------------------------------------------------------
 
reg invalid_inst_r;
 
 
 
always @ *
                   begin
                   begin
                        if (v_reg_ra < v_reg_rb)
    case (1'b1)
                            v_sr[`OR32_SR_F] = 1'b1;
       inst_add_w,
                        else
       inst_addc_w,
                            v_sr[`OR32_SR_F] = 1'b0;
       inst_and_w,
 
       inst_or_w,
 
       inst_sll_w,
 
       inst_sra_w,
 
       inst_srl_w,
 
       inst_sub_w,
 
       inst_xor_w,
 
       inst_addi_w,
 
       inst_andi_w,
 
       inst_bf_w,
 
       inst_bnf_w,
 
       inst_j_w,
 
       inst_jal_w,
 
       inst_jalr_w,
 
       inst_jr_w,
 
       inst_lbs_w,
 
       inst_lhs_w,
 
       inst_lws_w,
 
       inst_lbz_w,
 
       inst_lhz_w,
 
       inst_lwz_w,
 
       inst_mfspr_w,
 
       inst_mtspr_w,
 
       inst_movhi_w,
 
       inst_nop_w,
 
       inst_ori_w,
 
       inst_rfe_w,
 
       inst_sb_w,
 
       inst_sh_w,
 
       inst_sw_w,
 
       inst_xori_w,
 
       inst_slli_w,
 
       inst_srai_w,
 
       inst_srli_w,
 
       inst_sfeq_w,
 
       inst_sfeqi_w,
 
       inst_sfges_w,
 
       inst_sfgesi_w,
 
       inst_sfgeu_w,
 
       inst_sfgeui_w,
 
       inst_sfgts_w,
 
       inst_sfgtsi_w,
 
       inst_sfgtu_w,
 
       inst_sfgtui_w,
 
       inst_sfles_w,
 
       inst_sflesi_w,
 
       inst_sfleu_w,
 
       inst_sfleui_w,
 
       inst_sflts_w,
 
       inst_sfltsi_w,
 
       inst_sfltu_w,
 
       inst_sfltui_w,
 
       inst_sfne_w,
 
       inst_sfnei_w,
 
       inst_sys_w,
 
       inst_trap_w:
 
          invalid_inst_r = 1'b0;
 
       default:
 
          invalid_inst_r = 1'b1;
 
    endcase
                   end
                   end
 
 
                   `INST_OR32_SFLTUI: // l.sfltui
//-----------------------------------------------------------------
 
// Execute: ALU control
 
//-----------------------------------------------------------------
 
always @ (posedge clk_i or posedge rst_i)
                   begin
                   begin
                        if (v_reg_ra < v_imm_int32)
   if (rst_i == 1'b1)
                            v_sr[`OR32_SR_F] = 1'b1;
   begin
                        else
       r_e_alu_func         <= `ALU_NONE;
                            v_sr[`OR32_SR_F] = 1'b0;
       r_e_alu_a            <= 32'h00000000;
 
       r_e_alu_b            <= 32'h00000000;
 
       r_e_rd               <= 5'b00000;
                   end
                   end
 
   else
                   `INST_OR32_SFNE: // l.sfne
   begin
 
       //---------------------------------------------------------------
 
       // Instruction not ready
 
       //---------------------------------------------------------------
 
       if (~execute_inst_r | stall_inst_r)
                   begin
                   begin
                        if (v_reg_ra != v_reg_rb)
           // Insert load result?
                            v_sr[`OR32_SR_F] = 1'b1;
           if (load_insert)
 
           begin
 
               // Feed load result into pipeline
 
               r_e_alu_func   <= `ALU_NONE;
 
               r_e_alu_a      <= load_result;
 
               r_e_alu_b      <= 32'b0;
 
               r_e_rd         <= r_load_rd;
 
           end
                        else
                        else
                            v_sr[`OR32_SR_F] = 1'b0;
           begin
 
               // No ALU operation (output == input_a)
 
               r_e_alu_func   <= `ALU_NONE;
 
               r_e_alu_a      <= 32'b0;
 
               r_e_alu_b      <= 32'b0;
 
               r_e_rd         <= 5'b0;
                   end
                   end
 
       end
                   `INST_OR32_SFNEI: // l.sfnei
       //---------------------------------------------------------------
 
       // Valid instruction
 
       //---------------------------------------------------------------
 
       else if (~invalid_inst_r)
                   begin
                   begin
                        if (v_reg_ra != v_imm_int32)
           // Update ALU input flops
                            v_sr[`OR32_SR_F] = 1'b1;
           r_e_alu_func         <= alu_func_r;
 
           r_e_alu_a            <= alu_input_a_r;
 
           r_e_alu_b            <= alu_input_b_r;
 
 
 
           // Branch and link (Rd = LR/R9)
 
           if (branch_link_r)
 
              r_e_rd            <= 5'd9;
 
           // Instruction with register writeback
 
           else if (write_rd_r)
 
              r_e_rd            <= reg_rd_i;
                        else
                        else
                            v_sr[`OR32_SR_F] = 1'b0;
              r_e_rd            <= 5'b0;
                   end
                   end
 
 
                   default:
 
                   begin
 
                       fault_o <= 1'b1;
 
                       v_exception = 1'b1;
 
                       v_vector = ISR_VECTOR + `VECTOR_ILLEGAL_INST;
 
                   end
                   end
               endcase
 
           end
           end
 
 
           `INST_OR32_SH: // l.sh
//-----------------------------------------------------------------
 
// Execute: Update executed PC / opcode
 
//-----------------------------------------------------------------
 
always @ (posedge clk_i or posedge rst_i)
           begin
           begin
               v_mem_addr = (v_reg_ra + v_store_imm);
   if (rst_i == 1'b1)
               dmem_addr_o <= v_mem_addr;
 
               r_mem_access <= 1'b1;
 
               case (v_mem_addr[1:0])
 
                   2'b00 :
 
                   begin
                   begin
                       dmem_data_out_o <= {v_reg_rb[15:0],16'h0000};
       r_e_opcode           <= 32'h00000000;
                       dmem_wr_o <= 4'b1100;
       r_e_opcode_pc        <= 32'h00000000;
                       v_store_pending  = 1'b1;
 
 
       r_stall              <= 1'b0;
                   end
                   end
                   2'b10 :
   else
                   begin
                   begin
                       dmem_data_out_o <= {16'h0000,v_reg_rb[15:0]};
       r_stall              <= stall_inst_r;
                       dmem_wr_o <= 4'b0011;
 
                       v_store_pending  = 1'b1;
       // Instruction not ready
                   end
       if (~execute_inst_r | stall_inst_r)
                   default :
 
                   begin
                   begin
                       dmem_data_out_o <= 32'h00000000;
           // Store bubble opcode
                       dmem_wr_o <= 4'b0000;
           r_e_opcode            <= `OPCODE_INST_BUBBLE;
                   end
           r_e_opcode_pc         <= opcode_pc_i;
               endcase
 
           end
           end
 
       // Valid instruction
           `INST_OR32_SW: // l.sw
       else if (~invalid_inst_r)
           begin
           begin
               v_mem_addr = (v_reg_ra + v_store_imm);
           // Store opcode
               dmem_addr_o <= v_mem_addr;
           r_e_opcode            <= opcode_i;
               dmem_data_out_o <= v_reg_rb;
           r_e_opcode_pc         <= opcode_pc_i;
               dmem_wr_o <= 4'b1111;
 
               r_mem_access <= 1'b1;
 
               v_store_pending  = 1'b1;
 
 
 
`ifdef CONF_CORE_DEBUG
        `ifdef CONF_CORE_TRACE
               $display(" Store R%d to 0x%08x = 0x%08x", reg_rb_i, {v_mem_addr[31:2],2'b00}, v_reg_rb);
           $display("%08x: Execute 0x%08x", opcode_pc_i, opcode_i);
 
           $display(" rA[%d] = 0x%08x", reg_ra_i, reg_ra_r);
 
           $display(" rB[%d] = 0x%08x", reg_rb_i, reg_rb_r);
`endif
`endif
           end
           end
 
   end
 
end
 
 
          `INST_OR32_MISC:
//-----------------------------------------------------------------
 
// Execute: Branch / exceptions
 
//-----------------------------------------------------------------
 
always @ (posedge clk_i or posedge rst_i)
          begin
          begin
               case (v_mem_data_in[31:24])
   if (rst_i == 1'b1)
                   `INST_OR32_SYS: // l.sys
 
                   begin
                   begin
                       v_exception = 1'b1;
       r_pc_branch          <= 32'h00000000;
                       v_vector = ISR_VECTOR + `VECTOR_SYSCALL;
       r_pc_fetch           <= 1'b0;
                   end
 
 
 
                   `INST_OR32_TRAP: // l.trap
       // Status registers
                   begin
       r_epc                <= 32'h00000000;
                       v_exception = 1'b1;
       r_sr                 <= 32'h00000000;
                       v_vector = ISR_VECTOR + `VECTOR_TRAP;
       r_esr                <= 32'h00000000;
                       break_o <= 1'b1;
 
                   end
 
 
 
                   default :
       fault_o              <= 1'b0;
                   begin
 
                       fault_o <= 1'b1;
 
                       v_exception = 1'b1;
 
                       v_vector = ISR_VECTOR + `VECTOR_ILLEGAL_INST;
 
                   end
 
               endcase
 
           end
 
 
 
           `INST_OR32_XORI: // l.xori
       r_nmi                <= 1'b0;
           begin
 
               r_e_alu_func <= `ALU_XOR;
 
               r_e_alu_a <= v_reg_ra;
 
               r_e_alu_b <= v_imm_int32;
 
               v_write_rd = 1'b1;
 
           end
           end
 
   else
           default :
 
           begin
           begin
               fault_o <= 1'b1;
      // Record NMI in-case it can't be processed this cycle
               v_exception = 1'b1;
      if (nmi_i)
               v_vector = ISR_VECTOR + `VECTOR_ILLEGAL_INST;
          r_nmi             <= 1'b1;
           end
 
       endcase
 
 
 
       //---------------------------------------------------------------
       // Reset branch request
       // Branch logic
       r_pc_fetch           <= 1'b0;
       //---------------------------------------------------------------
 
 
 
       // If relative branch, calculate target before possible interrupt/exception
       // Update SR
       if (v_branch == 1'b1)
       r_sr                 <= next_sr_r;
       begin
 
           v_offset = {v_target[29:0],2'b00};
 
           v_pc     = (opcode_pc_i + v_offset);
 
       end
 
 
 
       // Pipeline stall due to load result not ready
       // Instruction ready
       if (v_stall == 1'b1)
       if (execute_inst_r & ~stall_inst_r)
 
       begin
 
           // Exception: Instruction opcode not valid / supported, invalid PC
 
           if (invalid_inst_r || (opcode_pc_i[1:0] != 2'b00))
       begin
       begin
            // No exceptions whilst stalled
                // Save PC of next instruction
 
                r_epc       <= next_pc_r;
 
                r_esr       <= next_sr_r;
 
 
 
                // Disable further interrupts
 
                r_sr        <= 32'b0;
 
 
 
                // Set PC to exception vector
 
                if (invalid_inst_r)
 
                    r_pc_branch <= ISR_VECTOR + `VECTOR_ILLEGAL_INST;
 
                else
 
                    r_pc_branch <= ISR_VECTOR + `VECTOR_BUS_ERROR;
 
                r_pc_fetch  <= 1'b1;
 
 
 
                fault_o     <= 1'b1;
       end
       end
       // Exception (Fault/Syscall/Break)
           // Exception: Syscall / Break
       else if (v_exception == 1'b1)
           else if (branch_except_r)
       begin
       begin
            // Save PC of next instruction
            // Save PC of next instruction
            r_epc       <= v_pc;
                r_epc       <= next_pc_r;
 
                r_esr       <= next_sr_r;
 
 
            // Disable further interrupts
            // Disable further interrupts
            r_esr       <= v_sr;
                r_sr        <= 32'b0;
            v_sr         = 0;
 
 
 
            // Set PC to exception vector
            // Set PC to exception vector
            v_pc         = v_vector;
                r_pc_branch <= branch_target_r;
            r_pc_branch <= v_pc;
 
            r_pc_fetch  <= 1'b1;
            r_pc_fetch  <= 1'b1;
 
 
`ifdef CONF_CORE_DEBUG
`ifdef CONF_CORE_DEBUG
           $display(" Exception 0x%08x", v_vector);
               $display(" Exception 0x%08x", branch_target_r);
`endif
`endif
       end
       end
       // Non-maskable interrupt
       // Non-maskable interrupt
       else if (nmi_i | r_nmi)
       else if (nmi_i | r_nmi)
       begin
       begin
            r_nmi       <= 1'b0;
            r_nmi       <= 1'b0;
 
 
            // Save PC of next instruction
            // Save PC of next instruction
            r_epc       <= v_pc;
                if (branch_r)
 
                    r_epc <= branch_target_r;
 
                // Next expected PC (current PC + 4)
 
                else
 
                    r_epc <= next_pc_r;
 
 
 
                r_esr       <= next_sr_r;
 
 
            // Disable further interrupts
            // Disable further interrupts
            r_esr       <= v_sr;
                r_sr        <= 32'b0;
            v_sr         = 0;
 
 
 
            // Set PC to exception vector
            // Set PC to exception vector
            v_pc         = ISR_VECTOR + `VECTOR_NMI;
                r_pc_branch <= ISR_VECTOR + `VECTOR_NMI;
            r_pc_branch <= v_pc;
 
            r_pc_fetch  <= 1'b1;
            r_pc_fetch  <= 1'b1;
 
 
`ifdef CONF_CORE_DEBUG
`ifdef CONF_CORE_DEBUG
           $display(" NMI 0x%08x", v_pc);
               $display(" NMI 0x%08x", ISR_VECTOR + `VECTOR_NMI);
`endif
`endif
       end
       end
       // External interrupt
       // External interrupt
       else if (v_no_intr == 1'b0 &&
           else if (intr_i && next_sr_r[`OR32_SR_IEE])
                ((intr_i && v_sr[`OR32_SR_IEE])))
 
       begin
       begin
            // Save PC of next instruction & SR
            // Save PC of next instruction & SR
            r_epc       <= v_pc;
                if (branch_r)
 
                    r_epc <= branch_target_r;
 
                // Next expected PC (current PC + 4)
 
                else
 
                    r_epc <= next_pc_r;
 
 
 
                r_esr       <= next_sr_r;
 
 
            // Disable further interrupts
            // Disable further interrupts
            r_esr       <= v_sr;
                r_sr        <= 32'b0;
            v_sr         = 0;
 
 
 
            // Set PC to external interrupt vector
            // Set PC to external interrupt vector
            v_pc    = ISR_VECTOR + `VECTOR_EXTINT;
                r_pc_branch <= ISR_VECTOR + `VECTOR_EXTINT;
 
 
            r_pc_branch <= v_pc;
 
            r_pc_fetch  <= 1'b1;
            r_pc_fetch  <= 1'b1;
 
 
`ifdef CONF_CORE_DEBUG
`ifdef CONF_CORE_DEBUG
           $display(" External Interrupt 0x%08x", v_pc);
               $display(" External Interrupt 0x%08x", ISR_VECTOR + `VECTOR_EXTINT);
`endif
`endif
       end
       end
       // Handle relative branches (l.bf, l.bnf, l.j, l.jal)
           // Branch (l.bf, l.bnf, l.j, l.jal, l.jr, l.jalr, l.rfe)
       else if (v_branch == 1'b1)
           else if (branch_r)
       begin
       begin
            // Perform branch (already in v_pc)
                // Perform branch
            r_pc_branch    <= v_pc;
                r_pc_branch    <= branch_target_r;
            r_pc_fetch     <= 1'b1;
            r_pc_fetch     <= 1'b1;
 
 
`ifdef CONF_CORE_DEBUG
`ifdef CONF_CORE_DEBUG
           $display(" Branch to 0x%08x", v_pc);
               $display(" Branch to 0x%08x", branch_target_r);
`endif
`endif
       end
       end
       // Handle absolute jumps (l.jr, l.jalr, l.rfe)
           // Non branch
       else if (v_jmp == 1'b1)
           else
 
           begin
 
                // Update EPC / ESR which may have been updated
 
                // by an MTSPR write
 
                r_epc          <= next_epc_r;
 
                r_esr          <= next_esr_r;
 
           end
 
      end
 
   end
 
end
 
 
 
//-----------------------------------------------------------------
 
// Execute: Memory operations
 
//-----------------------------------------------------------------
 
always @ (posedge clk_i or posedge rst_i)
       begin
       begin
            // Perform branch
   if (rst_i == 1'b1)
            r_pc_branch    <= v_pc;
   begin
            r_pc_fetch     <= 1'b1;
       // Data memory
 
       dmem_addr_o          <= 32'h00000000;
 
       dmem_data_out_o      <= 32'h00000000;
 
       dmem_rd_o            <= 1'b0;
 
       dmem_wr_o            <= 4'b0000;
 
 
`ifdef CONF_CORE_DEBUG
       r_mem_load           <= 1'b0;
           $display(" Jump to 0x%08x", v_pc);
       r_mem_store          <= 1'b0;
`endif
       r_mem_access         <= 1'b0;
 
 
 
       r_load_rd            <= 5'b00000;
 
       r_load_inst          <= 8'h00;
 
       r_load_offset        <= 2'b00;
 
 
 
       d_mem_load           <= 1'b0;
 
   end
 
   else
 
   begin
 
 
 
       // If memory access accepted by slave
 
       if (dmem_accept_i)
 
       begin
 
           dmem_rd_o            <= 1'b0;
 
           dmem_wr_o            <= 4'b0000;
       end
       end
 
 
 
       r_mem_access     <= 1'b0;
 
       d_mem_load       <= r_mem_access & r_mem_load;
 
 
       // Update other registers with variable values
       // Pending accesses
       r_stall      <= v_stall;
       r_mem_load   <= load_pending;
       r_sr         <= v_sr;
       r_mem_store  <= store_pending;
 
 
       // Memory access?
 
       r_mem_load <= v_load_pending;
 
       r_mem_store<= v_store_pending;
 
 
 
       // No writeback required?
       //---------------------------------------------------------------
       if (v_write_rd == 1'b0)
       // Valid instruction
 
       //---------------------------------------------------------------
 
       if (execute_inst_r & ~stall_inst_r & ~invalid_inst_r)
       begin
       begin
           // Target register is R0 which is read-only
           // Branch and link (Rd = LR/R9)
           r_e_rd <= 5'b00000;
           if (branch_link_r)
 
           begin
 
              // Load outstanding, check if result target is being
 
              // overwritten (to avoid WAR hazard)
 
              if (r_load_rd == 5'd9)
 
                  // Ditch load result when it arrives
 
                  r_load_rd     <= 5'b00000;
       end
       end
       // Writeback required
           // Instruction with register writeback
       else
           else if (write_rd_r)
       begin
       begin
            // Load outstanding, check if result target is being
            // Load outstanding, check if result target is being
            // overwritten (to avoid WAR hazard)
            // overwritten (to avoid WAR hazard)
            if (v_check_load_rd && v_rd == r_load_rd)
              if (reg_rd_i == r_load_rd && ~load_inst_r)
 
                  // Ditch load result when it arrives
 
                  r_load_rd     <= 5'b00000;
 
           end
 
 
 
           case (1'b1)
 
 
 
             // l.lbs l.lhs l.lws l.lbz l.lhz l.lwz
 
             load_inst_r:
            begin
            begin
 
                 dmem_addr_o      <= mem_addr_r;
 
                 dmem_data_out_o  <= 32'h00000000;
 
                 dmem_rd_o        <= 1'b1;
 
 
 
                 // Mark load as pending
 
                 r_mem_load      <= 1'b1;
 
                 r_mem_access    <= 1'b1;
 
 
 
                 // Record target register
 
                 r_load_rd        <= reg_rd_i;
 
                 r_load_inst      <= inst_r;
 
                 r_load_offset    <= mem_addr_r[1:0];
 
 
            `ifdef CONF_CORE_DEBUG
            `ifdef CONF_CORE_DEBUG
                if (v_rd != 5'b0)
                 $display(" Load from 0x%08x to R%d", mem_addr_r, reg_rd_i);
                    $display("%08x: Load target overwrite, clear target (R%d)", opcode_pc_i, r_load_rd);
 
            `endif
            `endif
 
             end
 
 
                // Ditch load result when it arrives
             inst_sb_w: // l.sb
                r_load_rd <= 5'b00000;
             begin
 
                 dmem_addr_o <= mem_addr_r;
 
                 r_mem_access <= 1'b1;
 
                 case (mem_addr_r[1:0])
 
                     2'b00 :
 
                     begin
 
                         dmem_data_out_o  <= {reg_rb_r[7:0],24'h000000};
 
                         dmem_wr_o        <= 4'b1000;
 
                         r_mem_store      <= 1'b1;
 
                     end
 
                     2'b01 :
 
                     begin
 
                         dmem_data_out_o  <= {{8'h00,reg_rb_r[7:0]},16'h0000};
 
                         dmem_wr_o        <= 4'b0100;
 
                         r_mem_store      <= 1'b1;
 
                     end
 
                     2'b10 :
 
                     begin
 
                         dmem_data_out_o  <= {{16'h0000,reg_rb_r[7:0]},8'h00};
 
                         dmem_wr_o        <= 4'b0010;
 
                         r_mem_store      <= 1'b1;
 
                     end
 
                     2'b11 :
 
                     begin
 
                         dmem_data_out_o  <= {24'h000000,reg_rb_r[7:0]};
 
                         dmem_wr_o        <= 4'b0001;
 
                         r_mem_store      <= 1'b1;
 
                     end
 
                     default :
 
                     begin
 
                         dmem_data_out_o  <= 32'h00000000;
 
                         dmem_wr_o        <= 4'b0000;
 
                     end
 
                 endcase
            end
            end
 
 
            // Target Rd
            inst_sh_w: // l.sh
            r_e_rd <= v_rd;
            begin
 
                 dmem_addr_o <= mem_addr_r;
 
                 r_mem_access <= 1'b1;
 
                 case (mem_addr_r[1:0])
 
                     2'b00 :
 
                     begin
 
                         dmem_data_out_o  <= {reg_rb_r[15:0],16'h0000};
 
                         dmem_wr_o        <= 4'b1100;
 
                         r_mem_store      <= 1'b1;
 
                     end
 
                     2'b10 :
 
                     begin
 
                         dmem_data_out_o  <= {16'h0000,reg_rb_r[15:0]};
 
                         dmem_wr_o        <= 4'b0011;
 
                         r_mem_store      <= 1'b1;
 
                     end
 
                     default :
 
                     begin
 
                         dmem_data_out_o  <= 32'h00000000;
 
                         dmem_wr_o        <= 4'b0000;
 
                     end
 
                 endcase
 
            end
 
 
 
            inst_sw_w: // l.sw
 
            begin
 
                 dmem_addr_o      <= mem_addr_r;
 
                 dmem_data_out_o  <= reg_rb_r;
 
                 dmem_wr_o        <= 4'b1111;
 
                 r_mem_access     <= 1'b1;
 
                 r_mem_store      <= 1'b1;
 
 
 
  `ifdef CONF_CORE_DEBUG
 
                 $display(" Store R%d to 0x%08x = 0x%08x", reg_rb_i, {mem_addr_r[31:2],2'b00}, reg_rb_r);
 
  `endif
 
            end
 
            default:
 
                ;
 
         endcase
 
       end
 
   end
 
end
 
 
 
//-----------------------------------------------------------------
 
// Execute: Misc operations
 
//-----------------------------------------------------------------
 
always @ (posedge clk_i or posedge rst_i)
 
begin
 
   if (rst_i == 1'b1)
 
   begin
 
       break_o              <= 1'b0;
 
       icache_flush_o       <= 1'b0;
 
       dcache_flush_o       <= 1'b0;
 
   end
 
   else
 
   begin
 
       break_o              <= 1'b0;
 
       icache_flush_o       <= 1'b0;
 
       dcache_flush_o       <= 1'b0;
 
 
 
       //---------------------------------------------------------------
 
       // Valid instruction
 
       //---------------------------------------------------------------
 
       if (execute_inst_r & ~stall_inst_r & ~invalid_inst_r)
 
       begin
 
          case (1'b1)
 
          inst_mtspr_w: // l.mtspr
 
          begin
 
               case (mxspr_uint16_r)
 
                   // SR - Supervision register
 
                   `SPR_REG_SR:
 
                   begin
 
                       // Cache flush request?
 
                       icache_flush_o <= reg_rb_r[`OR32_SR_ICACHE_FLUSH];
 
                       dcache_flush_o <= reg_rb_r[`OR32_SR_DCACHE_FLUSH];
 
                   end
 
               endcase
 
          end
 
 
 
          inst_trap_w: // l.trap
 
              break_o <= 1'b1;
 
          default:
 
              ;
 
         endcase
       end
       end
   end
   end
end
end
 
 
 
//-----------------------------------------------------------------
 
// Execute: NOP (simulation) operations
 
//-----------------------------------------------------------------
 
`ifdef SIMULATION
 
    always @ (posedge clk_i or posedge rst_i)
 
    begin
 
       if (rst_i == 1'b1)
 
       begin
 
    `ifdef SIM_EXT_PUTC
 
          r_putc                <= 8'b0;
 
    `endif
 
       end
 
       else
 
       begin
 
    `ifdef SIM_EXT_PUTC
 
          r_putc                <= 8'b0;
 
    `endif
 
           //---------------------------------------------------------------
 
           // Valid instruction
 
           //---------------------------------------------------------------
 
           if (execute_inst_r & ~stall_inst_r & ~invalid_inst_r)
 
           begin
 
 
 
               case (1'b1)
 
               inst_nop_w: // l.nop
 
                begin
 
                    case (uint16_r)
 
                    // NOP_PUTC
 
                    16'h0004:
 
                    begin
 
      `ifdef SIM_EXT_PUTC
 
                      r_putc  <= reg_ra_r[7:0];
 
      `else
 
                      $write("%c", reg_ra_r[7:0]);
 
      `endif
 
                    end
 
                    // NOP
 
                    16'h0000: ;
 
                    endcase
 
                end
 
                default:
 
                    ;
 
             endcase
 
           end
 
       end
 
    end
 
`endif
 
 
//-------------------------------------------------------------------
//-------------------------------------------------------------------
// Assignments
// Assignments
//-------------------------------------------------------------------
//-------------------------------------------------------------------
 
 
assign branch_pc_o          = r_pc_branch;
assign branch_pc_o          = r_pc_branch;
Line 1370... Line 1609...
   endfunction
   endfunction
   function [31:0] get_pc_ex;
   function [31:0] get_pc_ex;
      // verilator public
      // verilator public
      get_pc_ex = r_e_opcode_pc;
      get_pc_ex = r_e_opcode_pc;
   endfunction
   endfunction
 
   function [7:0] get_putc;
 
      // verilator public
 
   `ifdef SIM_EXT_PUTC
 
      get_putc = r_putc;
 
   `else
 
      get_putc = 8'b0;
 
   `endif
 
   endfunction
`endif
`endif
 
 
endmodule
endmodule
 
 
 No newline at end of file
 No newline at end of file

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.