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

Subversion Repositories altor32

[/] [altor32/] [trunk/] [rtl/] [cpu_lite/] [altor32_lite.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 91... Line 91...
//-----------------------------------------------------------------
//-----------------------------------------------------------------
// Registers
// Registers
//-----------------------------------------------------------------
//-----------------------------------------------------------------
 
 
// PC
// PC
reg [31:0]  r_pc;
reg [31:0]  pc_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;
 
 
// 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;
 
 
// ALU Carry
// ALU Carry
wire        alu_carry_out;
wire        alu_carry_out_w;
wire        alu_carry_update;
wire        alu_carry_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;
wire        alu_flag_update;
wire        alu_flag_update;
 
 
// ALU operation selection
// ALU operation selection
reg [3:0]   r_e_alu_func;
reg [3:0]   ex_alu_func_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
 
 
wire [4:0]  w_ra;
wire [4:0]  ra_w;
wire [4:0]  w_rb;
wire [4:0]  rb_w;
wire [4:0]  w_rd;
wire [4:0]  rd_w;
 
 
wire [31:0] w_reg_ra;
wire [31:0] reg_ra_w;
wire [31:0] w_reg_rb;
wire [31:0] reg_rb_w;
 
 
reg [31:0]  r_opcode;
reg [31:0]  opcode_q;
 
 
reg [31:0]  r_load_result;
reg [31:0]  load_result_r;
 
 
reg [1:0]   mem_offset;
reg [1:0]   mem_offset_q;
 
 
// Current state
// Current state
parameter STATE_IDLE        = 0;
parameter STATE_IDLE        = 0;
parameter STATE_FETCH       = 1;
parameter STATE_FETCH       = 1;
parameter STATE_FETCH_WAIT  = 2;
parameter STATE_FETCH_WAIT  = 2;
parameter STATE_EXEC        = 3;
parameter STATE_EXEC        = 3;
parameter STATE_MEM         = 4;
parameter STATE_MEM         = 4;
parameter STATE_WRITE_BACK  = 5;
parameter STATE_WRITE_BACK  = 5;
 
 
reg [3:0]   state;
reg [3:0]   state_q;
 
 
//-----------------------------------------------------------------
//-----------------------------------------------------------------
// Instantiation
// 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),
Line 192... Line 192...
    .less_than_o(compare_lt_w),
    .less_than_o(compare_lt_w),
    .flag_update_o(alu_flag_update)
    .flag_update_o(alu_flag_update)
);
);
 
 
// Writeback result
// Writeback result
wire [31:0] w_write_res     = (state == STATE_MEM) ? r_load_result : r_e_result;
wire [31:0] w_write_res     = (state_q == STATE_MEM) ? load_result_r : ex_result_w;
 
 
// Writeback enable
// Writeback enable
wire        w_write_en      = (state == STATE_MEM & mem_ack_i) | (state == STATE_WRITE_BACK);
wire        w_write_en      = (state_q == STATE_MEM & mem_ack_i) | (state_q == STATE_WRITE_BACK);
 
 
// Register file
//-----------------------------------------------------------------
 
// [Xilinx] Register file
 
//-----------------------------------------------------------------
generate
generate
if (REGISTER_FILE_TYPE == "XILINX")
if (REGISTER_FILE_TYPE == "XILINX")
begin : REGFILE_XIL
begin : REGFILE_XIL
    altor32_regfile_xil
    altor32_regfile_xil
    #(
    #(
Line 213... Line 215...
        .clk_i(clk_i),
        .clk_i(clk_i),
        .rst_i(rst_i),
        .rst_i(rst_i),
        .wr_i(w_write_en),
        .wr_i(w_write_en),
 
 
        // Tri-port
        // Tri-port
        .rs_i(w_ra),
        .ra_i(ra_w),
        .rt_i(w_rb),
        .rb_i(rb_w),
        .rd_i(r_e_rd),
        .rd_i(ex_rd_q),
        .reg_rs_o(w_reg_ra),
        .reg_ra_o(reg_ra_w),
        .reg_rt_o(w_reg_rb),
        .reg_rb_o(reg_rb_w),
        .reg_rd_i(w_write_res)
        .reg_rd_i(w_write_res)
    );
    );
end
end
 
//-----------------------------------------------------------------
 
// [Altera] Register file
 
//-----------------------------------------------------------------
else if (REGISTER_FILE_TYPE == "ALTERA")
else if (REGISTER_FILE_TYPE == "ALTERA")
begin : REGFILE_ALT
begin : REGFILE_ALT
    altor32_regfile_alt
    altor32_regfile_alt
    #(
    #(
        .SUPPORT_32REGS(SUPPORT_32REGS)
        .SUPPORT_32REGS(SUPPORT_32REGS)
Line 235... Line 240...
        .clk_i(clk_i),
        .clk_i(clk_i),
        .rst_i(rst_i),
        .rst_i(rst_i),
        .wr_i(w_write_en),
        .wr_i(w_write_en),
 
 
        // Tri-port
        // Tri-port
        .rs_i(w_ra),
        .ra_i(ra_w),
        .rt_i(w_rb),
        .rb_i(rb_w),
        .rd_i(r_e_rd),
        .rd_i(ex_rd_q),
        .reg_rs_o(w_reg_ra),
        .reg_ra_o(reg_ra_w),
        .reg_rt_o(w_reg_rb),
        .reg_rb_o(reg_rb_w),
        .reg_rd_i(w_write_res)
        .reg_rd_i(w_write_res)
    );
    );
end
end
 
//-----------------------------------------------------------------
 
// [Simulation] Register file
 
//-----------------------------------------------------------------
else
else
begin : REGFILE_SIM
begin : REGFILE_SIM
    altor32_regfile_sim
    altor32_regfile_sim
    #(
    #(
        .SUPPORT_32REGS(SUPPORT_32REGS)
        .SUPPORT_32REGS(SUPPORT_32REGS)
Line 257... Line 265...
        .clk_i(clk_i),
        .clk_i(clk_i),
        .rst_i(rst_i),
        .rst_i(rst_i),
        .wr_i(w_write_en),
        .wr_i(w_write_en),
 
 
        // Tri-port
        // Tri-port
        .rs_i(w_ra),
        .ra_i(ra_w),
        .rt_i(w_rb),
        .rb_i(rb_w),
        .rd_i(r_e_rd),
        .rd_i(ex_rd_q),
        .reg_rs_o(w_reg_ra),
        .reg_ra_o(reg_ra_w),
        .reg_rt_o(w_reg_rb),
        .reg_rb_o(reg_rb_w),
        .reg_rd_i(w_write_res)
        .reg_rd_i(w_write_res)
    );
    );
end
end
endgenerate
endgenerate
 
 
Line 288... Line 296...
reg [31:0] shift_imm_r;
reg [31:0] shift_imm_r;
 
 
always @ *
always @ *
begin
begin
    // Instruction
    // Instruction
    inst_r               = {2'b00,r_opcode[31:26]};
    inst_r               = {2'b00,opcode_q[31:26]};
 
 
    // Sub instructions
    // Sub instructions
    alu_op_r             = {r_opcode[9:6],r_opcode[3:0]};
    alu_op_r             = {opcode_q[9:6],opcode_q[3:0]};
    sfxx_op_r            = {5'b00,r_opcode[31:21]} & `INST_OR32_SFMASK;
    sfxx_op_r            = {5'b00,opcode_q[31:21]} & `INST_OR32_SFMASK;
    shift_op_r           = r_opcode[7:6];
    shift_op_r           = opcode_q[7:6];
 
 
    // Branch target
    // Branch target
    target_int26_r       = sign_extend_imm26(r_opcode[25:0]);
    target_int26_r       = sign_extend_imm26(opcode_q[25:0]);
 
 
    // Store immediate
    // Store immediate
    store_int32_r        = sign_extend_imm16({r_opcode[25:21],r_opcode[10:0]});
    store_int32_r        = sign_extend_imm16({opcode_q[25:21],opcode_q[10:0]});
 
 
    // Signed & unsigned imm -> 32-bits
    // Signed & unsigned imm -> 32-bits
    uint16_r             = r_opcode[15:0];
    uint16_r             = opcode_q[15:0];
    int32_r              = sign_extend_imm16(r_opcode[15:0]);
    int32_r              = sign_extend_imm16(opcode_q[15:0]);
    uint32_r             = extend_imm16(r_opcode[15:0]);
    uint32_r             = extend_imm16(opcode_q[15:0]);
 
 
    // Register values [ra/rb]
    // Register values [ra/rb]
    reg_ra_r             = w_reg_ra;
    reg_ra_r             = reg_ra_w;
    reg_rb_r             = w_reg_rb;
    reg_rb_r             = reg_rb_w;
 
 
    // Shift ammount (from register[rb])
    // Shift ammount (from register[rb])
    shift_rb_r           = {26'b00,w_reg_rb[5:0]};
    shift_rb_r           = {26'b00,reg_rb_w[5:0]};
 
 
    // Shift ammount (from immediate)
    // Shift ammount (from immediate)
    shift_imm_r          = {26'b00,r_opcode[5:0]};
    shift_imm_r          = {26'b00,opcode_q[5:0]};
 
 
    // MTSPR/MFSPR operand
    // MTSPR/MFSPR operand
    mxspr_uint16_r       = (w_reg_ra[15:0] | {5'b00000,r_opcode[10:0]});
    mxspr_uint16_r       = (reg_ra_w[15:0] | {5'b00000,opcode_q[10:0]});
end
end
 
 
//-----------------------------------------------------------------
//-----------------------------------------------------------------
// Instruction Decode
// Instruction Decode
//-----------------------------------------------------------------
//-----------------------------------------------------------------
Line 381... Line 389...
wire inst_sfleu_w   = (inst_sfxx_w || inst_sfxxi_w) & (sfxx_op_r == `INST_OR32_SFLEU);  // l.sfleu
wire inst_sfleu_w   = (inst_sfxx_w || inst_sfxxi_w) & (sfxx_op_r == `INST_OR32_SFLEU);  // l.sfleu
wire inst_sflts_w   = (inst_sfxx_w || inst_sfxxi_w) & (sfxx_op_r == `INST_OR32_SFLTS);  // l.sflts
wire inst_sflts_w   = (inst_sfxx_w || inst_sfxxi_w) & (sfxx_op_r == `INST_OR32_SFLTS);  // l.sflts
wire inst_sfltu_w   = (inst_sfxx_w || inst_sfxxi_w) & (sfxx_op_r == `INST_OR32_SFLTU);  // l.sfltu
wire inst_sfltu_w   = (inst_sfxx_w || inst_sfxxi_w) & (sfxx_op_r == `INST_OR32_SFLTU);  // l.sfltu
wire inst_sfne_w    = (inst_sfxx_w || inst_sfxxi_w) & (sfxx_op_r == `INST_OR32_SFNE);   // l.sfne
wire inst_sfne_w    = (inst_sfxx_w || inst_sfxxi_w) & (sfxx_op_r == `INST_OR32_SFNE);   // l.sfne
 
 
wire inst_sys_w     = (inst_r == `INST_OR32_MISC) & (r_opcode[31:24] == `INST_OR32_SYS);  // l.sys
wire inst_sys_w     = (inst_r == `INST_OR32_MISC) & (opcode_q[31:24] == `INST_OR32_SYS);  // l.sys
wire inst_trap_w    = (inst_r == `INST_OR32_MISC) & (r_opcode[31:24] == `INST_OR32_TRAP); // l.trap
wire inst_trap_w    = (inst_r == `INST_OR32_MISC) & (opcode_q[31:24] == `INST_OR32_TRAP); // l.trap
 
 
//-----------------------------------------------------------------
//-----------------------------------------------------------------
// Load/Store operation?
// Load/Store operation?
//-----------------------------------------------------------------
//-----------------------------------------------------------------
reg         load_inst_r;
reg         load_inst_r;
Line 406... Line 414...
// Next State Logic
// Next State Logic
//-----------------------------------------------------------------
//-----------------------------------------------------------------
reg [3:0] next_state_r;
reg [3:0] next_state_r;
always @ *
always @ *
begin
begin
    next_state_r = state;
    next_state_r = state_q;
 
 
    case (state)
    case (state_q)
    //-----------------------------------------
    //-----------------------------------------
    // IDLE - 
    // IDLE - 
    //-----------------------------------------
    //-----------------------------------------
    STATE_IDLE :
    STATE_IDLE :
    begin
    begin
Line 469... Line 477...
 
 
// Update state
// Update state
always @ (posedge rst_i or posedge clk_i )
always @ (posedge rst_i or posedge clk_i )
begin
begin
   if (rst_i == 1'b1)
   if (rst_i == 1'b1)
        state   <= STATE_IDLE;
        state_q   <= STATE_IDLE;
   else
   else
        state   <= next_state_r;
        state_q   <= next_state_r;
end
end
 
 
//-----------------------------------------------------------------
//-----------------------------------------------------------------
// Memory Access / Instruction Fetch
// Memory Access / Instruction Fetch
//-----------------------------------------------------------------
//-----------------------------------------------------------------
Line 488... Line 496...
        mem_sel_o       <= 4'b0;
        mem_sel_o       <= 4'b0;
        mem_we_o        <= 1'b0;
        mem_we_o        <= 1'b0;
        mem_stb_o       <= 1'b0;
        mem_stb_o       <= 1'b0;
        mem_cyc_o       <= 1'b0;
        mem_cyc_o       <= 1'b0;
 
 
        r_opcode        <= 32'h00000000;
        opcode_q        <= 32'h00000000;
        mem_offset      <= 2'b0;
        mem_offset_q    <= 2'b0;
   end
   end
   else
   else
   begin
   begin
 
 
        if (~mem_stall_i)
        if (~mem_stall_i)
            mem_stb_o    <= 1'b0;
            mem_stb_o    <= 1'b0;
 
 
        case (state)
        case (state_q)
 
 
            //-----------------------------------------
            //-----------------------------------------
            // FETCH - Issue instruction fetch
            // FETCH - Issue instruction fetch
            //-----------------------------------------
            //-----------------------------------------
            STATE_FETCH :
            STATE_FETCH :
            begin
            begin
                // Start fetch from memory
                // Start fetch from memory
                mem_addr_o  <= r_pc;
                mem_addr_o  <= pc_q;
                mem_stb_o   <= 1'b1;
                mem_stb_o   <= 1'b1;
                mem_we_o    <= 1'b0;
                mem_we_o    <= 1'b0;
                mem_cyc_o   <= 1'b1;
                mem_cyc_o   <= 1'b1;
            end
            end
            //-----------------------------------------
            //-----------------------------------------
Line 518... Line 526...
            STATE_FETCH_WAIT :
            STATE_FETCH_WAIT :
            begin
            begin
                // Data ready from memory?
                // Data ready from memory?
                if (mem_ack_i)
                if (mem_ack_i)
                begin
                begin
                    r_opcode    <= mem_dat_i;
                    opcode_q    <= mem_dat_i;
                    mem_cyc_o   <= 1'b0;
                    mem_cyc_o   <= 1'b0;
                end
                end
            end
            end
            //-----------------------------------------
            //-----------------------------------------
            // EXEC - Issue read / write
            // EXEC - Issue read / write
            //-----------------------------------------            
            //-----------------------------------------            
            STATE_EXEC :
            STATE_EXEC :
            begin
            begin
            `ifdef CONF_CORE_TRACE
            `ifdef CONF_CORE_TRACE
                $display("%08x: Execute 0x%08x", r_pc, r_opcode);
                $display("%08x: Execute 0x%08x", pc_q, opcode_q);
                $display(" rA[%d] = 0x%08x", w_ra, reg_ra_r);
                $display(" rA[%d] = 0x%08x", ra_w, reg_ra_r);
                $display(" rB[%d] = 0x%08x", w_rb, reg_rb_r);
                $display(" rB[%d] = 0x%08x", rb_w, reg_rb_r);
            `endif
            `endif
 
 
                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
                 load_inst_r:
                 load_inst_r:
                 begin
                 begin
                     mem_addr_o      <= {mem_addr_r[31:2], 2'b0};
                     mem_addr_o      <= {mem_addr_r[31:2], 2'b0};
                     mem_offset      <= mem_addr_r[1:0];
                     mem_offset_q    <= mem_addr_r[1:0];
                     mem_dat_o       <= 32'h00000000;
                     mem_dat_o       <= 32'h00000000;
                     mem_sel_o       <= 4'b1111;
                     mem_sel_o       <= 4'b1111;
                     mem_we_o        <= 1'b0;
                     mem_we_o        <= 1'b0;
                     mem_stb_o       <= 1'b1;
                     mem_stb_o       <= 1'b1;
                     mem_cyc_o       <= 1'b1;
                     mem_cyc_o       <= 1'b1;
 
 
      `ifdef CONF_CORE_DEBUG
      `ifdef CONF_CORE_DEBUG
                     $display(" Load from 0x%08x to R%d", mem_addr_r, w_rd);
                     $display(" Load from 0x%08x to R%d", mem_addr_r, rd_w);
      `endif
      `endif
                 end
                 end
 
 
                 inst_sb_w: // l.sb
                 inst_sb_w: // l.sb
                 begin
                 begin
                     mem_addr_o      <= {mem_addr_r[31:2], 2'b0};
                     mem_addr_o      <= {mem_addr_r[31:2], 2'b0};
                     mem_offset      <= mem_addr_r[1:0];
                     mem_offset_q    <= mem_addr_r[1:0];
                     case (mem_addr_r[1:0])
                     case (mem_addr_r[1:0])
                         2'b00 :
                         2'b00 :
                         begin
                         begin
                             mem_dat_o       <= {reg_rb_r[7:0],24'h000000};
                             mem_dat_o       <= {reg_rb_r[7:0],24'h000000};
                             mem_sel_o       <= 4'b1000;
                             mem_sel_o       <= 4'b1000;
Line 595... Line 603...
                 end
                 end
 
 
                inst_sh_w: // l.sh
                inst_sh_w: // l.sh
                begin
                begin
                     mem_addr_o      <= {mem_addr_r[31:2], 2'b0};
                     mem_addr_o      <= {mem_addr_r[31:2], 2'b0};
                     mem_offset      <= mem_addr_r[1:0];
                     mem_offset_q    <= mem_addr_r[1:0];
                     case (mem_addr_r[1:0])
                     case (mem_addr_r[1:0])
                         2'b00 :
                         2'b00 :
                         begin
                         begin
                             mem_dat_o       <= {reg_rb_r[15:0],16'h0000};
                             mem_dat_o       <= {reg_rb_r[15:0],16'h0000};
                             mem_sel_o       <= 4'b1100;
                             mem_sel_o       <= 4'b1100;
Line 621... Line 629...
                end
                end
 
 
                inst_sw_w: // l.sw
                inst_sw_w: // l.sw
                begin
                begin
                     mem_addr_o      <= {mem_addr_r[31:2], 2'b0};
                     mem_addr_o      <= {mem_addr_r[31:2], 2'b0};
                     mem_offset      <= mem_addr_r[1:0];
                     mem_offset_q    <= mem_addr_r[1:0];
                     mem_dat_o       <= reg_rb_r;
                     mem_dat_o       <= reg_rb_r;
                     mem_sel_o       <= 4'b1111;
                     mem_sel_o       <= 4'b1111;
                     mem_we_o        <= 1'b1;
                     mem_we_o        <= 1'b1;
                     mem_stb_o       <= 1'b1;
                     mem_stb_o       <= 1'b1;
                     mem_cyc_o       <= 1'b1;
                     mem_cyc_o       <= 1'b1;
 
 
      `ifdef CONF_CORE_DEBUG
      `ifdef CONF_CORE_DEBUG
                     $display(" Store R%d to 0x%08x = 0x%08x", w_rb, {mem_addr_r[31:2],2'b00}, reg_rb_r);
                     $display(" Store R%d to 0x%08x = 0x%08x", rb_w, {mem_addr_r[31:2],2'b00}, reg_rb_r);
      `endif
      `endif
                end
                end
                default:
                default:
                    ;
                    ;
             endcase
             endcase
Line 657... Line 665...
 
 
assign mem_cti_o        = 3'b111;
assign mem_cti_o        = 3'b111;
 
 
// If simulation, RA = 03 if NOP instruction
// If simulation, RA = 03 if NOP instruction
`ifdef SIMULATION
`ifdef SIMULATION
    wire [7:0] v_fetch_inst = {2'b00, r_opcode[31:26]};
    wire [7:0] v_fetch_inst = {2'b00, opcode_q[31:26]};
    wire       v_is_nop     = (v_fetch_inst == `INST_OR32_NOP);
    wire       v_is_nop     = (v_fetch_inst == `INST_OR32_NOP);
    assign     w_ra         = v_is_nop ? 5'd3 : r_opcode[20:16];
    assign     ra_w         = v_is_nop ? 5'd3 : opcode_q[20:16];
`else
`else
    assign     w_ra         = r_opcode[20:16];
    assign     ra_w         = opcode_q[20:16];
`endif
`endif
 
 
assign w_rb        = r_opcode[15:11];
assign rb_w        = opcode_q[15:11];
assign w_rd        = r_opcode[25:21];
assign rd_w        = opcode_q[25:21];
 
 
//-----------------------------------------------------------------
//-----------------------------------------------------------------
// Next PC
// Next PC
//-----------------------------------------------------------------
//-----------------------------------------------------------------
reg [31:0]  next_pc_r;
reg [31:0]  next_pc_r;
 
 
always @ *
always @ *
begin
begin
    // Next expected PC (current PC + 4)
    // Next expected PC (current PC + 4)
    next_pc_r  = (r_pc + 4);
    next_pc_r  = (pc_q + 4);
end
end
 
 
//-----------------------------------------------------------------
//-----------------------------------------------------------------
// Next SR
// Next SR
//-----------------------------------------------------------------
//-----------------------------------------------------------------
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)
        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;
 
 
    case (1'b1)
    case (1'b1)
      inst_mtspr_w:
      inst_mtspr_w:
      begin
      begin
          case (mxspr_uint16_r)
          case (mxspr_uint16_r)
Line 712... Line 720...
            ;
            ;
          endcase
          endcase
      end
      end
      inst_rfe_w:
      inst_rfe_w:
      begin
      begin
          next_sr_r[`OR32_SR_F]         = r_esr[`OR32_SR_F];
          next_sr_r[`OR32_SR_F]         = esr_q[`OR32_SR_F];
          next_sr_r[`OR32_SR_CY]        = r_esr[`OR32_SR_CY];
          next_sr_r[`OR32_SR_CY]        = esr_q[`OR32_SR_CY];
          next_sr_r[`OR32_SR_IEE]       = r_esr[`OR32_SR_IEE];
          next_sr_r[`OR32_SR_IEE]       = esr_q[`OR32_SR_IEE];
      end
      end
      inst_sfxx_w,
      inst_sfxx_w,
      inst_sfxxi_w:
      inst_sfxxi_w:
           next_sr_r[`OR32_SR_F] = compare_result_r;
           next_sr_r[`OR32_SR_F] = compare_result_r;
      default:
      default:
Line 732... Line 740...
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 894... Line 902...
           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                = 32'b0;
               alu_input_a_r                = 32'b0;
               alu_input_a_r[`OR32_SR_F]    = r_esr[`OR32_SR_F];
               alu_input_a_r[`OR32_SR_F]    = esr_q[`OR32_SR_F];
               alu_input_a_r[`OR32_SR_CY]   = r_esr[`OR32_SR_CY];
               alu_input_a_r[`OR32_SR_CY]   = esr_q[`OR32_SR_CY];
               alu_input_a_r[`OR32_SR_IEE]  = r_esr[`OR32_SR_IEE];
               alu_input_a_r[`OR32_SR_IEE]  = esr_q[`OR32_SR_IEE];
               write_rd_r                   = 1'b1;
               write_rd_r                   = 1'b1;
           end
           end
           default:
           default:
              ;
              ;
        endcase
        endcase
Line 1041... Line 1049...
    branch_r        = 1'b0;
    branch_r        = 1'b0;
    branch_link_r   = 1'b0;
    branch_link_r   = 1'b0;
    branch_except_r = 1'b0;
    branch_except_r = 1'b0;
 
 
    // Default branch target is relative to current PC
    // Default branch target is relative to current PC
    branch_target_r = (r_pc + {target_int26_r[29:0],2'b00});
    branch_target_r = (pc_q + {target_int26_r[29:0],2'b00});
 
 
    case (1'b1)
    case (1'b1)
    inst_bf_w: // l.bf
    inst_bf_w: // l.bf
        branch_r      = r_sr[`OR32_SR_F];
        branch_r      = sr_q[`OR32_SR_F];
 
 
    inst_bnf_w: // l.bnf
    inst_bnf_w: // l.bnf
        branch_r      = ~r_sr[`OR32_SR_F];
        branch_r      = ~sr_q[`OR32_SR_F];
 
 
    inst_j_w: // l.j
    inst_j_w: // l.j
        branch_r      = 1'b1;
        branch_r      = 1'b1;
 
 
    inst_jal_w: // l.jal
    inst_jal_w: // l.jal
Line 1077... Line 1085...
    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 1168... Line 1176...
//-----------------------------------------------------------------
//-----------------------------------------------------------------
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
           // 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            <= w_rd;
              ex_rd_q            <= rd_w;
           else
           else
              r_e_rd            <= 5'b0;
              ex_rd_q            <= 5'b0;
   end
   end
end
end
 
 
//-----------------------------------------------------------------
//-----------------------------------------------------------------
// Execute: Branch / exceptions
// Execute: Branch / exceptions
//-----------------------------------------------------------------
//-----------------------------------------------------------------
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                 <= BOOT_VECTOR + `VECTOR_RESET;
       pc_q                 <= BOOT_VECTOR + `VECTOR_RESET;
 
 
       // 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;
 
 
       // Core disabled?
       // Core disabled?
       if (~enable_i)
       if (~enable_i)
       begin
       begin
           // Reset
           // Reset
           r_pc                 <= BOOT_VECTOR + `VECTOR_RESET;
           pc_q                 <= BOOT_VECTOR + `VECTOR_RESET;
 
 
           // 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
       // Write-back?
       // Write-back?
       else if (w_write_en)
       else if (w_write_en)
       begin
       begin
           // Update SR
           // Update SR
           r_sr                 <= next_sr_r;
           sr_q                 <= next_sr_r;
 
 
           // Exception: Instruction opcode not valid / supported, invalid PC
           // Exception: Instruction opcode not valid / supported, invalid PC
           if (invalid_inst_r || (r_pc[1:0] != 2'b00))
           if (invalid_inst_r || (pc_q[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    <= ISR_VECTOR + `VECTOR_ILLEGAL_INST;
                    pc_q    <= ISR_VECTOR + `VECTOR_ILLEGAL_INST;
                else
                else
                    r_pc    <= ISR_VECTOR + `VECTOR_BUS_ERROR;
                    pc_q    <= ISR_VECTOR + `VECTOR_BUS_ERROR;
 
 
                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_target_r;
                pc_q        <= branch_target_r;
 
 
    `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        <= ISR_VECTOR + `VECTOR_NMI;
                pc_q        <= ISR_VECTOR + `VECTOR_NMI;
 
 
    `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        <= ISR_VECTOR + `VECTOR_EXTINT;
                pc_q        <= ISR_VECTOR + `VECTOR_EXTINT;
 
 
    `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_target_r;
                pc_q        <= branch_target_r;
 
 
    `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_pc           <= next_pc_r;
                pc_q           <= next_pc_r;
                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
 
 
//-------------------------------------------------------------------
//-------------------------------------------------------------------
// Load result
// Load result
//-------------------------------------------------------------------
//-------------------------------------------------------------------
always @ *
always @ *
begin
begin
    r_load_result   = 32'h00000000;
    load_result_r   = 32'h00000000;
 
 
    case (1'b1)
    case (1'b1)
 
 
        inst_lbs_w, // l.lbs
        inst_lbs_w, // l.lbs
        inst_lbz_w: // l.lbz
        inst_lbz_w: // l.lbz
        begin
        begin
            case (mem_offset)
            case (mem_offset_q)
                2'b00 :   r_load_result[7:0] = mem_dat_i[31:24];
                2'b00 :   load_result_r[7:0] = mem_dat_i[31:24];
                2'b01 :   r_load_result[7:0] = mem_dat_i[23:16];
                2'b01 :   load_result_r[7:0] = mem_dat_i[23:16];
                2'b10 :   r_load_result[7:0] = mem_dat_i[15:8];
                2'b10 :   load_result_r[7:0] = mem_dat_i[15:8];
                2'b11 :   r_load_result[7:0] = mem_dat_i[7:0];
                2'b11 :   load_result_r[7:0] = mem_dat_i[7:0];
                default : ;
                default : ;
            endcase
            endcase
 
 
            // Sign extend LB
            // Sign extend LB
            if (inst_lbs_w && r_load_result[7])
            if (inst_lbs_w && load_result_r[7])
                r_load_result[31:8] = 24'hFFFFFF;
                load_result_r[31:8] = 24'hFFFFFF;
        end
        end
 
 
        inst_lhs_w, // l.lhs
        inst_lhs_w, // l.lhs
        inst_lhz_w: // l.lhz
        inst_lhz_w: // l.lhz
        begin
        begin
            case (mem_offset)
            case (mem_offset_q)
                2'b00 :   r_load_result[15:0] = mem_dat_i[31:16];
                2'b00 :   load_result_r[15:0] = mem_dat_i[31:16];
                2'b10 :   r_load_result[15:0] = mem_dat_i[15:0];
                2'b10 :   load_result_r[15:0] = mem_dat_i[15:0];
                default : ;
                default : ;
            endcase
            endcase
 
 
            // Sign extend LH
            // Sign extend LH
            if (inst_lhs_w && r_load_result[15])
            if (inst_lhs_w && load_result_r[15])
                r_load_result[31:16] = 16'hFFFF;
                load_result_r[31:16] = 16'hFFFF;
        end
        end
 
 
        // l.lwz l.lws
        // l.lwz l.lws
        default :
        default :
            r_load_result   = mem_dat_i;
            load_result_r   = mem_dat_i;
    endcase
    endcase
end
end
 
 
//-----------------------------------------------------------------
//-----------------------------------------------------------------
// Execute: Misc operations
// Execute: Misc operations
Line 1416... Line 1424...
    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
          if (inst_nop_w && state == STATE_EXEC)
          if (inst_nop_w && state_q == STATE_EXEC)
          begin
          begin
                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 1452... Line 1460...
// 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 = (state == STATE_EXEC) ? r_opcode : `OPCODE_INST_BUBBLE;
      get_opcode_ex = (state_q == STATE_EXEC) ? opcode_q : `OPCODE_INST_BUBBLE;
   endfunction
   endfunction
   function [31:0] get_pc_ex;
   function [31:0] get_pc_ex;
      // verilator public
      // verilator public
      get_pc_ex = r_pc;
      get_pc_ex = 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 = (state == STATE_EXEC) ? 1'b1 : 1'b0;
      get_reg_valid = (state_q == STATE_EXEC) ? 1'b1 : 1'b0;
   endfunction
   endfunction
   function [4:0] get_reg_ra;
   function [4:0] get_reg_ra;
      // verilator public
      // verilator public
      get_reg_ra = w_ra;
      get_reg_ra = ra_w;
   endfunction
   endfunction
   function [31:0] get_reg_ra_value;
   function [31:0] get_reg_ra_value;
      // verilator public
      // verilator public
      get_reg_ra_value = w_reg_ra;
      get_reg_ra_value = reg_ra_w;
   endfunction
   endfunction
   function [4:0] get_reg_rb;
   function [4:0] get_reg_rb;
      // verilator public
      // verilator public
      get_reg_rb = w_rb;
      get_reg_rb = rb_w;
   endfunction
   endfunction
   function [31:0] get_reg_rb_value;
   function [31:0] get_reg_rb_value;
      // verilator public
      // verilator public
      get_reg_rb_value = w_reg_rb;
      get_reg_rb_value = reg_rb_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.