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

Subversion Repositories altor32

[/] [altor32/] [trunk/] [rtl/] [cpu/] [altor32_exec.v] - Diff between revs 36 and 37

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

Rev 36 Rev 37
Line 8... Line 8...
//               Email: admin@ultra-embedded.com
//               Email: admin@ultra-embedded.com
//
//
//                       License: LGPL
//                       License: LGPL
//-----------------------------------------------------------------
//-----------------------------------------------------------------
//
//
// Copyright (C) 2011 - 2013 Ultra-Embedded.com
// Copyright (C) 2011 - 2014 Ultra-Embedded.com
//
//
// This source file may be used and distributed without         
// This source file may be used and distributed without         
// restriction provided that this copyright statement is not    
// restriction provided that this copyright statement is not    
// removed from the file and that any derivative work contains  
// removed from the file and that any derivative work contains  
// the original copyright notice and the associated disclaimer. 
// the original copyright notice and the associated disclaimer. 
Line 84... Line 84...
    // Reg D
    // Reg D
    input [4:0]         reg_rd_i /*verilator public*/,
    input [4:0]         reg_rd_i /*verilator public*/,
 
 
    // Output
    // Output
    output [31:0]       opcode_o /*verilator public*/,
    output [31:0]       opcode_o /*verilator public*/,
 
    output [31:0]       opcode_pc_o /*verilator public*/,
    output [4:0]        reg_rd_o /*verilator public*/,
    output [4:0]        reg_rd_o /*verilator public*/,
    output [31:0]       reg_rd_value_o /*verilator public*/,
    output [31:0]       reg_rd_value_o /*verilator public*/,
    output              mult_o /*verilator public*/,
    output              mult_o /*verilator public*/,
    output [31:0]       mult_res_o /*verilator public*/,
    output [31:0]       mult_res_o /*verilator public*/,
 
 
Line 122... Line 123...
//-----------------------------------------------------------------
//-----------------------------------------------------------------
// Registers
// Registers
//-----------------------------------------------------------------
//-----------------------------------------------------------------
 
 
// Branch PC
// Branch PC
reg [31:0] r_pc_branch;
reg [31:0]  pc_branch_q;
reg        r_pc_fetch;
reg         pc_fetch_q;
 
 
// Exception saved program counter
// Exception saved program counter
reg [31:0] r_epc;
reg [31:0]  epc_q;
 
 
// Supervisor register
// Supervisor register
reg [31:0] r_sr;
reg [31:0]  sr_q;
 
 
// Exception saved supervisor register
// Exception saved supervisor register
reg [31:0] r_esr;
reg [31:0]  esr_q;
 
 
// Destination register number (post execute stage)
// Destination register number (post execute stage)
reg [4:0] r_e_rd;
reg [4:0]   ex_rd_q;
 
 
// Current opcode (PC for debug)
// Current opcode (PC for debug)
reg [31:0] r_e_opcode;
reg [31:0]  ex_opcode_q;
reg [31:0] r_e_opcode_pc;
reg [31:0]  ex_opcode_pc_q;
 
 
// ALU input A
// ALU input A
reg [31:0] r_e_alu_a;
reg [31:0]  ex_alu_a_q;
 
 
// ALU input B
// ALU input B
reg [31:0] r_e_alu_b;
reg [31:0]  ex_alu_b_q;
 
 
// ALU output
// ALU output
wire [31:0] r_e_result;
wire [31:0] ex_result_w;
 
 
// Resolved RA/RB register contents
// Resolved RA/RB register contents
wire [31:0] ra_value_resolved;
wire [31:0] ra_resolved_w;
wire [31:0] rb_value_resolved;
wire [31:0] rb_resolved_w;
wire        operand_resolved;
wire        operand_resolved_w;
wire        resolve_failed;
wire        resolve_failed_w;
 
 
// ALU Carry
// ALU Carry
wire alu_carry_out;
wire        alu_carry_out_w;
wire alu_carry_update;
wire        alu_carry_update_w;
wire alu_flag_update;
wire        alu_flag_update_w;
 
 
// ALU Comparisons
// ALU Comparisons
wire compare_equal_w;
wire compare_equal_w;
wire compare_gts_w;
wire compare_gts_w;
wire compare_gt_w;
wire compare_gt_w;
wire compare_lts_w;
wire compare_lts_w;
wire compare_lt_w;
wire compare_lt_w;
 
 
// ALU operation selection
// ALU operation selection
reg [3:0] r_e_alu_func;
reg [3:0]   ex_alu_func_q;
 
 
// Load instruction details
// Load instruction details
reg [4:0] r_load_rd;
reg [4:0]   load_rd_q;
reg [7:0] r_load_inst;
reg [7:0]   load_inst_q;
reg [1:0] r_load_offset;
reg [1:0]   load_offset_q;
 
 
// Load forwarding
// Load forwarding
wire         load_insn;
wire        load_inst_w;
wire [31:0]  load_result;
wire [31:0] load_result_w;
 
 
// Memory access?
// Memory access?
reg r_mem_load;
reg         mem_load_q;
reg r_mem_store;
reg         mem_store_q;
reg r_mem_access;
reg         mem_access_q;
 
 
wire load_pending;
wire        load_pending_w;
wire store_pending;
wire        store_pending_w;
wire load_insert;
wire        load_insert_w;
wire load_stall;
wire        load_stall_w;
 
 
reg d_mem_load;
reg         d_mem_load_q;
 
 
// Delayed NMI
// Delayed NMI
reg r_nmi;
reg         nmi_q;
 
 
// SIM PUTC
// SIM PUTC
`ifdef SIM_EXT_PUTC
`ifdef SIM_EXT_PUTC
    reg [7:0] r_putc;
    reg [7:0] putc_q;
`endif
`endif
 
 
//-----------------------------------------------------------------
//-----------------------------------------------------------------
// Instantiation
 
//-----------------------------------------------------------------
 
 
 
// ALU
// ALU
 
//-----------------------------------------------------------------
altor32_alu alu
altor32_alu alu
(
(
    // ALU operation select
    // ALU operation select
    .op_i(r_e_alu_func),
    .op_i(ex_alu_func_q),
 
 
    // Operands
    // Operands
    .a_i(r_e_alu_a),
    .a_i(ex_alu_a_q),
    .b_i(r_e_alu_b),
    .b_i(ex_alu_b_q),
    .c_i(r_sr[`OR32_SR_CY]),
    .c_i(sr_q[`OR32_SR_CY]),
 
 
    // Result
    // Result
    .p_o(r_e_result),
    .p_o(ex_result_w),
 
 
    // Carry
    // Carry
    .c_o(alu_carry_out),
    .c_o(alu_carry_out_w),
    .c_update_o(alu_carry_update),
    .c_update_o(alu_carry_update_w),
 
 
    // Comparisons
    // Comparisons
    .equal_o(compare_equal_w),
    .equal_o(compare_equal_w),
    .greater_than_signed_o(compare_gts_w),
    .greater_than_signed_o(compare_gts_w),
    .greater_than_o(compare_gt_w),
    .greater_than_o(compare_gt_w),
    .less_than_signed_o(compare_lts_w),
    .less_than_signed_o(compare_lts_w),
    .less_than_o(compare_lt_w),
    .less_than_o(compare_lt_w),
    .flag_update_o(alu_flag_update)
    .flag_update_o(alu_flag_update_w)
);
);
 
 
 
//-----------------------------------------------------------------
// Load result forwarding
// Load result forwarding
 
//-----------------------------------------------------------------
altor32_lfu
altor32_lfu
u_lfu
u_lfu
(
(
    // Opcode
    // Opcode
    .opcode_i(r_load_inst),
    .opcode_i(load_inst_q),
 
 
    // Memory load result
    // Memory load result
    .mem_result_i(dmem_data_in_i),
    .mem_result_i(dmem_data_in_i),
    .mem_offset_i(r_load_offset),
    .mem_offset_i(load_offset_q),
 
 
    // Result
    // Result
    .load_result_o(load_result),
    .load_result_o(load_result_w),
    .load_insn_o(load_insn)
    .load_insn_o(load_inst_w)
);
);
 
 
 
//-----------------------------------------------------------------
// Load / store pending logic
// Load / store pending logic
 
//-----------------------------------------------------------------
altor32_lsu
altor32_lsu
u_lsu
u_lsu
(
(
    // Current instruction
    // Current instruction
    .opcode_valid_i(opcode_valid_i & ~r_pc_fetch),
    .opcode_valid_i(opcode_valid_i & ~pc_fetch_q),
    .opcode_i({2'b00,opcode_i[31:26]}),
    .opcode_i({2'b00,opcode_i[31:26]}),
 
 
    // Load / Store pending
    // Load / Store pending
    .load_pending_i(r_mem_load),
    .load_pending_i(mem_load_q),
    .store_pending_i(r_mem_store),
    .store_pending_i(mem_store_q),
 
 
    // Load dest register
    // Load dest register
    .rd_load_i(r_load_rd),
    .rd_load_i(load_rd_q),
 
 
    // Load insn in WB stage
    // Load insn in WB stage
    .load_wb_i(d_mem_load),
    .load_wb_i(d_mem_load_q),
 
 
    // Memory status
    // Memory status
    .mem_access_i(r_mem_access),
    .mem_access_i(mem_access_q),
    .mem_ack_i(dmem_ack_i),
    .mem_ack_i(dmem_ack_i),
 
 
    // Load / store still pending
    // Load / store still pending
    .load_pending_o(load_pending),
    .load_pending_o(load_pending_w),
    .store_pending_o(store_pending),
    .store_pending_o(store_pending_w),
 
 
    // Insert load result into pipeline
    // Insert load result into pipeline
    .write_result_o(load_insert),
    .write_result_o(load_insert_w),
 
 
    // Stall pipeline due
    // Stall pipeline due
    .stall_o(load_stall)
    .stall_o(load_stall_w)
);
);
 
 
 
//-----------------------------------------------------------------
// Operand forwarding
// Operand forwarding
 
//-----------------------------------------------------------------
altor32_dfu
altor32_dfu
u_dfu
u_dfu
(
(
    // Input registers
    // Input registers
    .ra_i(reg_ra_i),
    .ra_i(reg_ra_i),
Line 293... Line 298...
    // Input register contents
    // Input register contents
    .ra_regval_i(reg_ra_value_i),
    .ra_regval_i(reg_ra_value_i),
    .rb_regval_i(reg_rb_value_i),
    .rb_regval_i(reg_rb_value_i),
 
 
    // Dest register (EXEC stage)
    // Dest register (EXEC stage)
    .rd_ex_i(r_e_rd),
    .rd_ex_i(ex_rd_q),
 
 
    // Dest register (WB stage)
    // Dest register (WB stage)
    .rd_wb_i(wb_rd_i),
    .rd_wb_i(wb_rd_i),
 
 
    // Load pending / target
    // Load pending / target
    .load_pending_i(load_pending),
    .load_pending_i(load_pending_w),
    .rd_load_i(r_load_rd),
    .rd_load_i(load_rd_q),
 
 
    // Multiplier status
    // Multiplier status
    .mult_lo_ex_i(1'b0),
    .mult_lo_ex_i(1'b0),
    .mult_hi_ex_i(1'b0),
    .mult_hi_ex_i(1'b0),
    .mult_lo_wb_i(1'b0),
    .mult_lo_wb_i(1'b0),
Line 312... Line 317...
 
 
    // Multiplier result
    // Multiplier result
    .result_mult_i(64'b0),
    .result_mult_i(64'b0),
 
 
    // Result (EXEC)
    // Result (EXEC)
    .result_ex_i(r_e_result),
    .result_ex_i(ex_result_w),
 
 
    // Result (WB)
    // Result (WB)
    .result_wb_i(wb_rd_value_i),
    .result_wb_i(wb_rd_value_i),
 
 
    // Resolved register values
    // Resolved register values
    .result_ra_o(ra_value_resolved),
    .result_ra_o(ra_resolved_w),
    .result_rb_o(rb_value_resolved),
    .result_rb_o(rb_resolved_w),
 
 
    // Operands required forwarding
    // Operands required forwarding
    .resolved_o(operand_resolved),
    .resolved_o(operand_resolved_w),
 
 
    // Stall due to failed resolve
    // Stall due to failed resolve
    .stall_o(resolve_failed)
    .stall_o(resolve_failed_w)
);
);
 
 
//-----------------------------------------------------------------
//-----------------------------------------------------------------
// Opcode decode
// Opcode decode
//-----------------------------------------------------------------
//-----------------------------------------------------------------
Line 368... Line 373...
    uint16_r             = opcode_i[15:0];
    uint16_r             = opcode_i[15:0];
    int32_r              = sign_extend_imm16(opcode_i[15:0]);
    int32_r              = sign_extend_imm16(opcode_i[15:0]);
    uint32_r             = extend_imm16(opcode_i[15:0]);
    uint32_r             = extend_imm16(opcode_i[15:0]);
 
 
    // Register values [ra/rb]
    // Register values [ra/rb]
    reg_ra_r             = ra_value_resolved;
    reg_ra_r             = ra_resolved_w;
    reg_rb_r             = rb_value_resolved;
    reg_rb_r             = rb_resolved_w;
 
 
    // Shift ammount (from register[rb])
    // Shift ammount (from register[rb])
    shift_rb_r           = {26'b00,rb_value_resolved[5:0]};
    shift_rb_r           = {26'b00,rb_resolved_w[5:0]};
 
 
    // Shift ammount (from immediate)
    // Shift ammount (from immediate)
    shift_imm_r          = {26'b00,opcode_i[5:0]};
    shift_imm_r          = {26'b00,opcode_i[5:0]};
 
 
    // MTSPR/MFSPR operand
    // MTSPR/MFSPR operand
Line 459... Line 464...
begin
begin
    execute_inst_r  = 1'b1;
    execute_inst_r  = 1'b1;
    stall_inst_r    = 1'b0;
    stall_inst_r    = 1'b0;
 
 
    // No opcode ready or branch delay slot
    // No opcode ready or branch delay slot
    if (~opcode_valid_i | r_pc_fetch)
    if (~opcode_valid_i | pc_fetch_q)
        execute_inst_r  = 1'b0;
        execute_inst_r  = 1'b0;
    // Valid instruction, but load result / operand not ready
    // Valid instruction, but load result / operand not ready
    else if (resolve_failed | load_stall |
    else if (resolve_failed_w | load_stall_w |
            (operand_resolved & (inst_mfspr_w | inst_mtspr_w)))
            (operand_resolved_w & (inst_mfspr_w | inst_mtspr_w)))
        stall_inst_r    = 1'b1;
        stall_inst_r    = 1'b1;
end
end
 
 
//-----------------------------------------------------------------
//-----------------------------------------------------------------
// Next PC
// Next PC
Line 485... Line 490...
//-----------------------------------------------------------------
//-----------------------------------------------------------------
reg [31:0]  next_sr_r;
reg [31:0]  next_sr_r;
reg         compare_result_r;
reg         compare_result_r;
always @ *
always @ *
begin
begin
    next_sr_r = r_sr;
    next_sr_r = sr_q;
 
 
    // Update SR.F
    // Update SR.F
    if (alu_flag_update)
    if (alu_flag_update_w)
        next_sr_r[`OR32_SR_F] = compare_result_r;
        next_sr_r[`OR32_SR_F] = compare_result_r;
 
 
    // Latch carry if updated
    // Latch carry if updated
    if (alu_carry_update)
    if (alu_carry_update_w)
        next_sr_r[`OR32_SR_CY] = alu_carry_out;
        next_sr_r[`OR32_SR_CY] = alu_carry_out_w;
 
 
    // If valid instruction, check if SR needs updating
    // If valid instruction, check if SR needs updating
    if (execute_inst_r & ~stall_inst_r)
    if (execute_inst_r & ~stall_inst_r)
    begin
    begin
      case (1'b1)
      case (1'b1)
Line 516... Line 521...
          default:
          default:
            ;
            ;
          endcase
          endcase
      end
      end
      inst_rfe_w:
      inst_rfe_w:
          next_sr_r = r_esr;
          next_sr_r = esr_q;
      default:
      default:
        ;
        ;
      endcase
      endcase
    end
    end
end
end
Line 531... Line 536...
reg [31:0]  next_epc_r;
reg [31:0]  next_epc_r;
reg [31:0]  next_esr_r;
reg [31:0]  next_esr_r;
 
 
always @ *
always @ *
begin
begin
    next_epc_r = r_epc;
    next_epc_r = epc_q;
    next_esr_r = r_esr;
    next_esr_r = esr_q;
 
 
    case (1'b1)
    case (1'b1)
    inst_mtspr_w: // l.mtspr
    inst_mtspr_w: // l.mtspr
    begin
    begin
       case (mxspr_uint16_r)
       case (mxspr_uint16_r)
Line 690... Line 695...
           end
           end
 
 
           // EPCR - EPC Exception saved PC
           // EPCR - EPC Exception saved PC
           `SPR_REG_EPCR:
           `SPR_REG_EPCR:
           begin
           begin
               alu_input_a_r  = r_epc;
               alu_input_a_r  = epc_q;
               write_rd_r     = 1'b1;
               write_rd_r     = 1'b1;
           end
           end
 
 
           // ESR - Exception saved SR
           // ESR - Exception saved SR
           `SPR_REG_ESR:
           `SPR_REG_ESR:
           begin
           begin
               alu_input_a_r  = r_esr;
               alu_input_a_r  = esr_q;
               write_rd_r     = 1'b1;
               write_rd_r     = 1'b1;
           end
           end
           default:
           default:
              ;
              ;
        endcase
        endcase
Line 983... Line 988...
    end
    end
 
 
    inst_rfe_w: // l.rfe
    inst_rfe_w: // l.rfe
    begin
    begin
        branch_r        = 1'b1;
        branch_r        = 1'b1;
        branch_target_r = r_epc;
        branch_target_r = epc_q;
    end
    end
 
 
    inst_sys_w: // l.sys
    inst_sys_w: // l.sys
    begin
    begin
        branch_r        = 1'b1;
        branch_r        = 1'b1;
Line 1074... Line 1079...
//-----------------------------------------------------------------
//-----------------------------------------------------------------
always @ (posedge clk_i or posedge rst_i)
always @ (posedge clk_i or posedge rst_i)
begin
begin
   if (rst_i == 1'b1)
   if (rst_i == 1'b1)
   begin
   begin
       r_e_alu_func         <= `ALU_NONE;
       ex_alu_func_q         <= `ALU_NONE;
       r_e_alu_a            <= 32'h00000000;
       ex_alu_a_q            <= 32'h00000000;
       r_e_alu_b            <= 32'h00000000;
       ex_alu_b_q            <= 32'h00000000;
       r_e_rd               <= 5'b00000;
       ex_rd_q               <= 5'b00000;
   end
   end
   else
   else
   begin
   begin
       //---------------------------------------------------------------
       //---------------------------------------------------------------
       // Instruction not ready
       // Instruction not ready
       //---------------------------------------------------------------
       //---------------------------------------------------------------
       if (~execute_inst_r | stall_inst_r)
       if (~execute_inst_r | stall_inst_r)
       begin
       begin
           // Insert load result?
           // Insert load result?
           if (load_insert)
           if (load_insert_w)
           begin
           begin
               // Feed load result into pipeline
               // Feed load result into pipeline
               r_e_alu_func   <= `ALU_NONE;
               ex_alu_func_q   <= `ALU_NONE;
               r_e_alu_a      <= load_result;
               ex_alu_a_q      <= load_result_w;
               r_e_alu_b      <= 32'b0;
               ex_alu_b_q      <= 32'b0;
               r_e_rd         <= r_load_rd;
               ex_rd_q         <= load_rd_q;
           end
           end
           else
           else
           begin
           begin
               // No ALU operation (output == input_a)
               // No ALU operation (output == input_a)
               r_e_alu_func   <= `ALU_NONE;
               ex_alu_func_q   <= `ALU_NONE;
               r_e_alu_a      <= 32'b0;
               ex_alu_a_q      <= 32'b0;
               r_e_alu_b      <= 32'b0;
               ex_alu_b_q      <= 32'b0;
               r_e_rd         <= 5'b0;
               ex_rd_q         <= 5'b0;
           end
           end
       end
       end
       //---------------------------------------------------------------
       //---------------------------------------------------------------
       // Valid instruction
       // Valid instruction
       //---------------------------------------------------------------
       //---------------------------------------------------------------
       else
       else
       begin
       begin
           // Update ALU input flops
           // Update ALU input flops
           r_e_alu_func         <= alu_func_r;
           ex_alu_func_q         <= alu_func_r;
           r_e_alu_a            <= alu_input_a_r;
           ex_alu_a_q            <= alu_input_a_r;
           r_e_alu_b            <= alu_input_b_r;
           ex_alu_b_q            <= alu_input_b_r;
 
 
           // Branch and link (Rd = LR/R9)
           // Branch and link (Rd = LR/R9)
           if (branch_link_r)
           if (branch_link_r)
              r_e_rd            <= 5'd9;
              ex_rd_q            <= 5'd9;
           // Instruction with register writeback
           // Instruction with register writeback
           else if (write_rd_r)
           else if (write_rd_r)
              r_e_rd            <= reg_rd_i;
              ex_rd_q            <= reg_rd_i;
           else
           else
              r_e_rd            <= 5'b0;
              ex_rd_q            <= 5'b0;
       end
       end
   end
   end
end
end
 
 
//-----------------------------------------------------------------
//-----------------------------------------------------------------
Line 1133... Line 1138...
//-----------------------------------------------------------------
//-----------------------------------------------------------------
always @ (posedge clk_i or posedge rst_i)
always @ (posedge clk_i or posedge rst_i)
begin
begin
   if (rst_i == 1'b1)
   if (rst_i == 1'b1)
   begin
   begin
       r_e_opcode           <= 32'h00000000;
       ex_opcode_q           <= 32'h00000000;
       r_e_opcode_pc        <= 32'h00000000;
       ex_opcode_pc_q        <= 32'h00000000;
   end
   end
   else
   else
   begin
   begin
       // Instruction not ready
       // Instruction not ready
       if (~execute_inst_r | stall_inst_r)
       if (~execute_inst_r | stall_inst_r)
       begin
       begin
           // Store bubble opcode
           // Store bubble opcode
           r_e_opcode            <= `OPCODE_INST_BUBBLE;
           ex_opcode_q            <= `OPCODE_INST_BUBBLE;
           r_e_opcode_pc         <= opcode_pc_i;
           ex_opcode_pc_q         <= opcode_pc_i;
       end
       end
       // Valid instruction
       // Valid instruction
       else
       else
       begin
       begin
           // Store opcode
           // Store opcode
           r_e_opcode            <= opcode_i;
           ex_opcode_q            <= opcode_i;
           r_e_opcode_pc         <= opcode_pc_i;
           ex_opcode_pc_q         <= opcode_pc_i;
 
 
        `ifdef CONF_CORE_TRACE
        `ifdef CONF_CORE_TRACE
           $display("%08x: Execute 0x%08x", opcode_pc_i, opcode_i);
           $display("%08x: Execute 0x%08x", opcode_pc_i, opcode_i);
           $display(" rA[%d] = 0x%08x", reg_ra_i, reg_ra_r);
           $display(" rA[%d] = 0x%08x", reg_ra_i, reg_ra_r);
           $display(" rB[%d] = 0x%08x", reg_rb_i, reg_rb_r);
           $display(" rB[%d] = 0x%08x", reg_rb_i, reg_rb_r);
Line 1168... Line 1173...
//-----------------------------------------------------------------
//-----------------------------------------------------------------
always @ (posedge clk_i or posedge rst_i)
always @ (posedge clk_i or posedge rst_i)
begin
begin
   if (rst_i == 1'b1)
   if (rst_i == 1'b1)
   begin
   begin
       r_pc_branch          <= 32'h00000000;
       pc_branch_q          <= 32'h00000000;
       r_pc_fetch           <= 1'b0;
       pc_fetch_q           <= 1'b0;
 
 
       // Status registers
       // Status registers
       r_epc                <= 32'h00000000;
       epc_q                <= 32'h00000000;
       r_sr                 <= 32'h00000000;
       sr_q                 <= 32'h00000000;
       r_esr                <= 32'h00000000;
       esr_q                <= 32'h00000000;
 
 
       fault_o              <= 1'b0;
       fault_o              <= 1'b0;
 
 
       r_nmi                <= 1'b0;
       nmi_q                <= 1'b0;
   end
   end
   else
   else
   begin
   begin
      // Record NMI in-case it can't be processed this cycle
      // Record NMI in-case it can't be processed this cycle
      if (nmi_i)
      if (nmi_i)
          r_nmi             <= 1'b1;
          nmi_q             <= 1'b1;
 
 
       // Reset branch request
       // Reset branch request
       r_pc_fetch           <= 1'b0;
       pc_fetch_q           <= 1'b0;
 
 
       // Update SR
       // Update SR
       r_sr                 <= next_sr_r;
       sr_q                 <= next_sr_r;
 
 
       // Instruction ready
       // Instruction ready
       if (execute_inst_r & ~stall_inst_r)
       if (execute_inst_r & ~stall_inst_r)
       begin
       begin
           // Exception: Instruction opcode not valid / supported, invalid PC
           // Exception: Instruction opcode not valid / supported, invalid PC
           if (invalid_inst_r || (opcode_pc_i[1:0] != 2'b00))
           if (invalid_inst_r || (opcode_pc_i[1:0] != 2'b00))
           begin
           begin
                // Save PC of next instruction
                // Save PC of next instruction
                r_epc       <= next_pc_r;
                epc_q       <= next_pc_r;
                r_esr       <= next_sr_r;
                esr_q       <= next_sr_r;
 
 
                // Disable further interrupts
                // Disable further interrupts
                r_sr        <= 32'b0;
                sr_q        <= 32'b0;
 
 
                // Set PC to exception vector
                // Set PC to exception vector
                if (invalid_inst_r)
                if (invalid_inst_r)
                    r_pc_branch <= ISR_VECTOR + `VECTOR_ILLEGAL_INST;
                    pc_branch_q <= ISR_VECTOR + `VECTOR_ILLEGAL_INST;
                else
                else
                    r_pc_branch <= ISR_VECTOR + `VECTOR_BUS_ERROR;
                    pc_branch_q <= ISR_VECTOR + `VECTOR_BUS_ERROR;
                r_pc_fetch  <= 1'b1;
                pc_fetch_q  <= 1'b1;
 
 
                fault_o     <= 1'b1;
                fault_o     <= 1'b1;
           end
           end
           // Exception: Syscall / Break
           // Exception: Syscall / Break
           else if (branch_except_r)
           else if (branch_except_r)
           begin
           begin
                // Save PC of next instruction
                // Save PC of next instruction
                r_epc       <= next_pc_r;
                epc_q       <= next_pc_r;
                r_esr       <= next_sr_r;
                esr_q       <= next_sr_r;
 
 
                // Disable further interrupts
                // Disable further interrupts
                r_sr        <= 32'b0;
                sr_q        <= 32'b0;
 
 
                // Set PC to exception vector
                // Set PC to exception vector
                r_pc_branch <= branch_target_r;
                pc_branch_q <= branch_target_r;
                r_pc_fetch  <= 1'b1;
                pc_fetch_q  <= 1'b1;
 
 
    `ifdef CONF_CORE_DEBUG
    `ifdef CONF_CORE_DEBUG
               $display(" Exception 0x%08x", branch_target_r);
               $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 | nmi_q)
           begin
           begin
                r_nmi       <= 1'b0;
                nmi_q       <= 1'b0;
 
 
                // Save PC of next instruction
                // Save PC of next instruction
                if (branch_r)
                if (branch_r)
                    r_epc <= branch_target_r;
                    epc_q <= branch_target_r;
                // Next expected PC (current PC + 4)
                // Next expected PC (current PC + 4)
                else
                else
                    r_epc <= next_pc_r;
                    epc_q <= next_pc_r;
 
 
                r_esr       <= next_sr_r;
                esr_q       <= next_sr_r;
 
 
                // Disable further interrupts
                // Disable further interrupts
                r_sr        <= 32'b0;
                sr_q        <= 32'b0;
 
 
                // Set PC to exception vector
                // Set PC to exception vector
                r_pc_branch <= ISR_VECTOR + `VECTOR_NMI;
                pc_branch_q <= ISR_VECTOR + `VECTOR_NMI;
                r_pc_fetch  <= 1'b1;
                pc_fetch_q  <= 1'b1;
 
 
    `ifdef CONF_CORE_DEBUG
    `ifdef CONF_CORE_DEBUG
               $display(" NMI 0x%08x", ISR_VECTOR + `VECTOR_NMI);
               $display(" NMI 0x%08x", ISR_VECTOR + `VECTOR_NMI);
    `endif
    `endif
           end
           end
           // External interrupt
           // External interrupt
           else if (intr_i && next_sr_r[`OR32_SR_IEE])
           else if (intr_i && next_sr_r[`OR32_SR_IEE])
           begin
           begin
                // Save PC of next instruction & SR
                // Save PC of next instruction & SR
                if (branch_r)
                if (branch_r)
                    r_epc <= branch_target_r;
                    epc_q <= branch_target_r;
                // Next expected PC (current PC + 4)
                // Next expected PC (current PC + 4)
                else
                else
                    r_epc <= next_pc_r;
                    epc_q <= next_pc_r;
 
 
                r_esr       <= next_sr_r;
                esr_q       <= next_sr_r;
 
 
                // Disable further interrupts
                // Disable further interrupts
                r_sr        <= 32'b0;
                sr_q        <= 32'b0;
 
 
                // Set PC to external interrupt vector
                // Set PC to external interrupt vector
                r_pc_branch <= ISR_VECTOR + `VECTOR_EXTINT;
                pc_branch_q <= ISR_VECTOR + `VECTOR_EXTINT;
                r_pc_fetch  <= 1'b1;
                pc_fetch_q  <= 1'b1;
 
 
    `ifdef CONF_CORE_DEBUG
    `ifdef CONF_CORE_DEBUG
               $display(" External Interrupt 0x%08x", ISR_VECTOR + `VECTOR_EXTINT);
               $display(" External Interrupt 0x%08x", ISR_VECTOR + `VECTOR_EXTINT);
    `endif
    `endif
           end
           end
           // Branch (l.bf, l.bnf, l.j, l.jal, l.jr, l.jalr, l.rfe)
           // Branch (l.bf, l.bnf, l.j, l.jal, l.jr, l.jalr, l.rfe)
           else if (branch_r)
           else if (branch_r)
           begin
           begin
                // Perform branch
                // Perform branch
                r_pc_branch    <= branch_target_r;
                pc_branch_q    <= branch_target_r;
                r_pc_fetch     <= 1'b1;
                pc_fetch_q     <= 1'b1;
 
 
    `ifdef CONF_CORE_DEBUG
    `ifdef CONF_CORE_DEBUG
               $display(" Branch to 0x%08x", branch_target_r);
               $display(" Branch to 0x%08x", branch_target_r);
    `endif
    `endif
           end
           end
           // Non branch
           // Non branch
           else
           else
           begin
           begin
                // Update EPC / ESR which may have been updated
                // Update EPC / ESR which may have been updated
                // by an MTSPR write
                // by an MTSPR write
                r_epc          <= next_epc_r;
                epc_q          <= next_epc_r;
                r_esr          <= next_esr_r;
                esr_q          <= next_esr_r;
           end
           end
      end
      end
   end
   end
end
end
 
 
Line 1318... Line 1323...
       dmem_we_o            <= 1'b0;
       dmem_we_o            <= 1'b0;
       dmem_sel_o           <= 4'b0000;
       dmem_sel_o           <= 4'b0000;
       dmem_stb_o           <= 1'b0;
       dmem_stb_o           <= 1'b0;
       dmem_cyc_o           <= 1'b0;
       dmem_cyc_o           <= 1'b0;
 
 
       r_mem_load           <= 1'b0;
       mem_load_q           <= 1'b0;
       r_mem_store          <= 1'b0;
       mem_store_q          <= 1'b0;
       r_mem_access         <= 1'b0;
       mem_access_q         <= 1'b0;
 
 
       r_load_rd            <= 5'b00000;
       load_rd_q            <= 5'b00000;
       r_load_inst          <= 8'h00;
       load_inst_q          <= 8'h00;
       r_load_offset        <= 2'b00;
       load_offset_q        <= 2'b00;
 
 
       d_mem_load           <= 1'b0;
       d_mem_load_q         <= 1'b0;
   end
   end
   else
   else
   begin
   begin
 
 
       // If memory access accepted by slave
       // If memory access accepted by slave
Line 1338... Line 1343...
           dmem_stb_o   <= 1'b0;
           dmem_stb_o   <= 1'b0;
 
 
       if (dmem_ack_i)
       if (dmem_ack_i)
            dmem_cyc_o  <= 1'b0;
            dmem_cyc_o  <= 1'b0;
 
 
       r_mem_access     <= 1'b0;
       mem_access_q     <= 1'b0;
       d_mem_load       <= r_mem_access & r_mem_load;
       d_mem_load_q     <= mem_access_q & mem_load_q;
 
 
       // Pending accesses
       // Pending accesses
       r_mem_load   <= load_pending;
       mem_load_q   <= load_pending_w;
       r_mem_store  <= store_pending;
       mem_store_q  <= store_pending_w;
 
 
       //---------------------------------------------------------------
       //---------------------------------------------------------------
       // Valid instruction
       // Valid instruction
       //---------------------------------------------------------------
       //---------------------------------------------------------------
       if (execute_inst_r & ~stall_inst_r)
       if (execute_inst_r & ~stall_inst_r)
Line 1355... Line 1360...
           // Branch and link (Rd = LR/R9)
           // Branch and link (Rd = LR/R9)
           if (branch_link_r)
           if (branch_link_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 (r_load_rd == 5'd9)
              if (load_rd_q == 5'd9)
                  // Ditch load result when it arrives
                  // Ditch load result when it arrives
                  r_load_rd     <= 5'b00000;
                  load_rd_q     <= 5'b00000;
           end
           end
           // Instruction with register writeback
           // Instruction with register writeback
           else if (write_rd_r)
           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 (reg_rd_i == r_load_rd && ~load_inst_r)
              if (reg_rd_i == load_rd_q && ~load_inst_r)
                  // Ditch load result when it arrives
                  // Ditch load result when it arrives
                  r_load_rd     <= 5'b00000;
                  load_rd_q     <= 5'b00000;
           end
           end
 
 
           case (1'b1)
           case (1'b1)
 
 
             // l.lbs l.lhs l.lws l.lbz l.lhz l.lwz
             // l.lbs l.lhs l.lws l.lbz l.lhz l.lwz
Line 1382... Line 1387...
                 dmem_we_o        <= 1'b0;
                 dmem_we_o        <= 1'b0;
                 dmem_stb_o       <= 1'b1;
                 dmem_stb_o       <= 1'b1;
                 dmem_cyc_o       <= 1'b1;
                 dmem_cyc_o       <= 1'b1;
 
 
                 // Mark load as pending
                 // Mark load as pending
                 r_mem_load      <= 1'b1;
                 mem_load_q      <= 1'b1;
                 r_mem_access    <= 1'b1;
                 mem_access_q    <= 1'b1;
 
 
                 // Record target register
                 // Record target register
                 r_load_rd        <= reg_rd_i;
                 load_rd_q        <= reg_rd_i;
                 r_load_inst      <= inst_r;
                 load_inst_q      <= inst_r;
                 r_load_offset    <= mem_addr_r[1:0];
                 load_offset_q    <= mem_addr_r[1:0];
 
 
  `ifdef CONF_CORE_DEBUG
  `ifdef CONF_CORE_DEBUG
                 $display(" Load from 0x%08x to R%d", mem_addr_r, reg_rd_i);
                 $display(" Load from 0x%08x to R%d", mem_addr_r, reg_rd_i);
  `endif
  `endif
             end
             end
 
 
             inst_sb_w: // l.sb
             inst_sb_w: // l.sb
             begin
             begin
                 dmem_addr_o <= mem_addr_r;
                 dmem_addr_o <= mem_addr_r;
                 r_mem_access <= 1'b1;
                 mem_access_q <= 1'b1;
                 case (mem_addr_r[1:0])
                 case (mem_addr_r[1:0])
                     2'b00 :
                     2'b00 :
                     begin
                     begin
                         dmem_data_out_o  <= {reg_rb_r[7:0],24'h000000};
                         dmem_data_out_o  <= {reg_rb_r[7:0],24'h000000};
                         dmem_sel_o       <= 4'b1000;
                         dmem_sel_o       <= 4'b1000;
                         dmem_we_o        <= 1'b1;
                         dmem_we_o        <= 1'b1;
                         dmem_stb_o       <= 1'b1;
                         dmem_stb_o       <= 1'b1;
                         dmem_cyc_o       <= 1'b1;
                         dmem_cyc_o       <= 1'b1;
                         r_mem_store      <= 1'b1;
                         mem_store_q      <= 1'b1;
                     end
                     end
                     2'b01 :
                     2'b01 :
                     begin
                     begin
                         dmem_data_out_o  <= {{8'h00,reg_rb_r[7:0]},16'h0000};
                         dmem_data_out_o  <= {{8'h00,reg_rb_r[7:0]},16'h0000};
                         dmem_sel_o       <= 4'b0100;
                         dmem_sel_o       <= 4'b0100;
                         dmem_we_o        <= 1'b1;
                         dmem_we_o        <= 1'b1;
                         dmem_stb_o       <= 1'b1;
                         dmem_stb_o       <= 1'b1;
                         dmem_cyc_o       <= 1'b1;
                         dmem_cyc_o       <= 1'b1;
                         r_mem_store      <= 1'b1;
                         mem_store_q      <= 1'b1;
                     end
                     end
                     2'b10 :
                     2'b10 :
                     begin
                     begin
                         dmem_data_out_o  <= {{16'h0000,reg_rb_r[7:0]},8'h00};
                         dmem_data_out_o  <= {{16'h0000,reg_rb_r[7:0]},8'h00};
                         dmem_sel_o       <= 4'b0010;
                         dmem_sel_o       <= 4'b0010;
                         dmem_we_o        <= 1'b1;
                         dmem_we_o        <= 1'b1;
                         dmem_stb_o       <= 1'b1;
                         dmem_stb_o       <= 1'b1;
                         dmem_cyc_o       <= 1'b1;
                         dmem_cyc_o       <= 1'b1;
                         r_mem_store      <= 1'b1;
                         mem_store_q      <= 1'b1;
                     end
                     end
                     2'b11 :
                     2'b11 :
                     begin
                     begin
                         dmem_data_out_o  <= {24'h000000,reg_rb_r[7:0]};
                         dmem_data_out_o  <= {24'h000000,reg_rb_r[7:0]};
                         dmem_sel_o       <= 4'b0001;
                         dmem_sel_o       <= 4'b0001;
                         dmem_we_o        <= 1'b1;
                         dmem_we_o        <= 1'b1;
                         dmem_stb_o       <= 1'b1;
                         dmem_stb_o       <= 1'b1;
                         dmem_cyc_o       <= 1'b1;
                         dmem_cyc_o       <= 1'b1;
                         r_mem_store      <= 1'b1;
                         mem_store_q      <= 1'b1;
                     end
                     end
                     default :
                     default :
                        ;
                        ;
                 endcase
                 endcase
             end
             end
 
 
            inst_sh_w: // l.sh
            inst_sh_w: // l.sh
            begin
            begin
                 dmem_addr_o <= mem_addr_r;
                 dmem_addr_o <= mem_addr_r;
                 r_mem_access <= 1'b1;
                 mem_access_q <= 1'b1;
                 case (mem_addr_r[1:0])
                 case (mem_addr_r[1:0])
                     2'b00 :
                     2'b00 :
                     begin
                     begin
                         dmem_data_out_o  <= {reg_rb_r[15:0],16'h0000};
                         dmem_data_out_o  <= {reg_rb_r[15:0],16'h0000};
                         dmem_sel_o       <= 4'b1100;
                         dmem_sel_o       <= 4'b1100;
                         dmem_we_o        <= 1'b1;
                         dmem_we_o        <= 1'b1;
                         dmem_stb_o       <= 1'b1;
                         dmem_stb_o       <= 1'b1;
                         dmem_cyc_o       <= 1'b1;
                         dmem_cyc_o       <= 1'b1;
                         r_mem_store      <= 1'b1;
                         mem_store_q      <= 1'b1;
                     end
                     end
                     2'b10 :
                     2'b10 :
                     begin
                     begin
                         dmem_data_out_o  <= {16'h0000,reg_rb_r[15:0]};
                         dmem_data_out_o  <= {16'h0000,reg_rb_r[15:0]};
                         dmem_sel_o       <= 4'b0011;
                         dmem_sel_o       <= 4'b0011;
                         dmem_we_o        <= 1'b1;
                         dmem_we_o        <= 1'b1;
                         dmem_stb_o       <= 1'b1;
                         dmem_stb_o       <= 1'b1;
                         dmem_cyc_o       <= 1'b1;
                         dmem_cyc_o       <= 1'b1;
                         r_mem_store      <= 1'b1;
                         mem_store_q      <= 1'b1;
                     end
                     end
                     default :
                     default :
                        ;
                        ;
                 endcase
                 endcase
            end
            end
Line 1477... Line 1482...
                 dmem_data_out_o  <= reg_rb_r;
                 dmem_data_out_o  <= reg_rb_r;
                 dmem_sel_o       <= 4'b1111;
                 dmem_sel_o       <= 4'b1111;
                 dmem_we_o        <= 1'b1;
                 dmem_we_o        <= 1'b1;
                 dmem_stb_o       <= 1'b1;
                 dmem_stb_o       <= 1'b1;
                 dmem_cyc_o       <= 1'b1;
                 dmem_cyc_o       <= 1'b1;
                 r_mem_access     <= 1'b1;
                 mem_access_q     <= 1'b1;
                 r_mem_store      <= 1'b1;
                 mem_store_q      <= 1'b1;
 
 
  `ifdef CONF_CORE_DEBUG
  `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);
                 $display(" Store R%d to 0x%08x = 0x%08x", reg_rb_i, {mem_addr_r[31:2],2'b00}, reg_rb_r);
  `endif
  `endif
            end
            end
Line 1545... Line 1550...
    always @ (posedge clk_i or posedge rst_i)
    always @ (posedge clk_i or posedge rst_i)
    begin
    begin
       if (rst_i == 1'b1)
       if (rst_i == 1'b1)
       begin
       begin
    `ifdef SIM_EXT_PUTC
    `ifdef SIM_EXT_PUTC
          r_putc                <= 8'b0;
          putc_q                <= 8'b0;
    `endif
    `endif
       end
       end
       else
       else
       begin
       begin
    `ifdef SIM_EXT_PUTC
    `ifdef SIM_EXT_PUTC
          r_putc                <= 8'b0;
          putc_q                <= 8'b0;
    `endif
    `endif
           //---------------------------------------------------------------
           //---------------------------------------------------------------
           // Valid instruction
           // Valid instruction
           //---------------------------------------------------------------
           //---------------------------------------------------------------
           if (execute_inst_r & ~stall_inst_r)
           if (execute_inst_r & ~stall_inst_r)
Line 1567... Line 1572...
                    case (uint16_r)
                    case (uint16_r)
                    // NOP_PUTC
                    // NOP_PUTC
                    16'h0004:
                    16'h0004:
                    begin
                    begin
      `ifdef SIM_EXT_PUTC
      `ifdef SIM_EXT_PUTC
                      r_putc  <= reg_ra_r[7:0];
                      putc_q  <= reg_ra_r[7:0];
      `else
      `else
                      $write("%c", reg_ra_r[7:0]);
                      $write("%c", reg_ra_r[7:0]);
      `endif
      `endif
                    end
                    end
                    // NOP
                    // NOP
Line 1588... Line 1593...
 
 
//-------------------------------------------------------------------
//-------------------------------------------------------------------
// Assignments
// Assignments
//-------------------------------------------------------------------
//-------------------------------------------------------------------
 
 
assign branch_pc_o          = r_pc_branch;
assign branch_pc_o          = pc_branch_q;
assign branch_o             = r_pc_fetch;
assign branch_o             = pc_fetch_q;
assign stall_o              = stall_inst_r;
assign stall_o              = stall_inst_r;
 
 
assign opcode_o             = r_e_opcode;
assign opcode_o             = ex_opcode_q;
 
assign opcode_pc_o          = ex_opcode_pc_q;
 
 
assign reg_rd_o             = r_e_rd;
assign reg_rd_o             = ex_rd_q;
assign reg_rd_value_o       = r_e_result;
assign reg_rd_value_o       = ex_result_w;
 
 
assign mult_o               = 1'b0;
assign mult_o               = 1'b0;
assign mult_res_o           = 32'b0;
assign mult_res_o           = 32'b0;
 
 
//-------------------------------------------------------------------
//-------------------------------------------------------------------
// Hooks for debug
// Hooks for debug
//-------------------------------------------------------------------
//-------------------------------------------------------------------
`ifdef verilator
`ifdef verilator
   function [31:0] get_opcode_ex;
   function [31:0] get_opcode_ex;
      // verilator public
      // verilator public
      get_opcode_ex = r_e_opcode;
      get_opcode_ex = ex_opcode_q;
   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 = ex_opcode_pc_q;
   endfunction
   endfunction
   function [7:0] get_putc;
   function [7:0] get_putc;
      // verilator public
      // verilator public
   `ifdef SIM_EXT_PUTC
   `ifdef SIM_EXT_PUTC
      get_putc = r_putc;
      get_putc = putc_q;
   `else
   `else
      get_putc = 8'b0;
      get_putc = 8'b0;
   `endif
   `endif
   endfunction
   endfunction
   function [0:0] get_reg_valid;
   function [0:0] get_reg_valid;
      // verilator public
      // verilator public
      get_reg_valid = ~(resolve_failed | load_stall | ~opcode_valid_i);
      get_reg_valid = ~(resolve_failed_w | load_stall_w | ~opcode_valid_i);
   endfunction
   endfunction
   function [4:0] get_reg_ra;
   function [4:0] get_reg_ra;
      // verilator public
      // verilator public
      get_reg_ra = reg_ra_i;
      get_reg_ra = reg_ra_i;
   endfunction
   endfunction
   function [31:0] get_reg_ra_value;
   function [31:0] get_reg_ra_value;
      // verilator public
      // verilator public
      get_reg_ra_value = ra_value_resolved;
      get_reg_ra_value = ra_resolved_w;
   endfunction
   endfunction
   function [4:0] get_reg_rb;
   function [4:0] get_reg_rb;
      // verilator public
      // verilator public
      get_reg_rb = reg_rb_i;
      get_reg_rb = reg_rb_i;
   endfunction
   endfunction
   function [31:0] get_reg_rb_value;
   function [31:0] get_reg_rb_value;
      // verilator public
      // verilator public
      get_reg_rb_value = rb_value_resolved;
      get_reg_rb_value = rb_resolved_w;
   endfunction
   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.