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

Subversion Repositories zipcpu

[/] [zipcpu/] [trunk/] [rtl/] [core/] [zipcpu.v] - Diff between revs 179 and 193

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

Rev 179 Rev 193
Line 104... Line 104...
//
//
//
//
//
//
`define CPU_CC_REG      4'he
`define CPU_CC_REG      4'he
`define CPU_PC_REG      4'hf
`define CPU_PC_REG      4'hf
`define CPU_CLRCACHE_BIT 14     // Floating point error flag, set on error
`define CPU_CLRCACHE_BIT 14     // Set to clear the I-cache, automatically clears
`define CPU_PHASE_BIT   13      // Floating point error flag, set on error
`define CPU_PHASE_BIT   13      // Set if we are executing the latter half of a VLIW
`define CPU_FPUERR_BIT  12      // Floating point error flag, set on error
`define CPU_FPUERR_BIT  12      // Floating point error flag, set on error
`define CPU_DIVERR_BIT  11      // Divide error flag, set on divide by zero
`define CPU_DIVERR_BIT  11      // Divide error flag, set on divide by zero
`define CPU_BUSERR_BIT  10      // Bus error flag, set on error
`define CPU_BUSERR_BIT  10      // Bus error flag, set on error
`define CPU_TRAP_BIT    9       // User TRAP has taken place
`define CPU_TRAP_BIT    9       // User TRAP has taken place
`define CPU_ILL_BIT     8       // Illegal instruction
`define CPU_ILL_BIT     8       // Illegal instruction
Line 137... Line 137...
                o_op_stall, o_pf_stall, o_i_count
                o_op_stall, o_pf_stall, o_i_count
`ifdef  DEBUG_SCOPE
`ifdef  DEBUG_SCOPE
                , o_debug
                , o_debug
`endif
`endif
                );
                );
        parameter       RESET_ADDRESS=32'h0100000, ADDRESS_WIDTH=24,
        parameter       RESET_ADDRESS=32'h0100000, ADDRESS_WIDTH=32,
                        LGICACHE=8;
                        LGICACHE=8;
`ifdef  OPT_MULTIPLY
`ifdef  OPT_MULTIPLY
        parameter       IMPLEMENT_MPY = `OPT_MULTIPLY;
        parameter       IMPLEMENT_MPY = `OPT_MULTIPLY;
`else
`else
        parameter       IMPLEMENT_MPY = 0;
        parameter       IMPLEMENT_MPY = 0;
Line 160... Line 160...
`ifdef  OPT_EARLY_BRANCHING
`ifdef  OPT_EARLY_BRANCHING
        parameter       EARLY_BRANCHING = 1;
        parameter       EARLY_BRANCHING = 1;
`else
`else
        parameter       EARLY_BRANCHING = 0;
        parameter       EARLY_BRANCHING = 0;
`endif
`endif
        parameter       AW=ADDRESS_WIDTH;
        localparam      AW=ADDRESS_WIDTH;
        input                   i_clk, i_rst, i_interrupt;
        input                   i_clk, i_rst, i_interrupt;
        // Debug interface -- inputs
        // Debug interface -- inputs
        input                   i_halt, i_clear_pf_cache;
        input                   i_halt, i_clear_pf_cache;
        input           [4:0]    i_dbg_reg;
        input           [4:0]    i_dbg_reg;
        input                   i_dbg_we;
        input                   i_dbg_we;
Line 323... Line 323...
        wire    [31:0]   alu_result;
        wire    [31:0]   alu_result;
        wire    [3:0]    alu_flags;
        wire    [3:0]    alu_flags;
        wire            alu_valid, alu_busy;
        wire            alu_valid, alu_busy;
        wire            set_cond;
        wire            set_cond;
        reg             alu_wr, alF_wr;
        reg             alu_wr, alF_wr;
        wire            alu_gie, alu_illegal_op, alu_illegal;
        wire            alu_gie, alu_illegal;
 
 
 
 
 
 
        wire    mem_ce, mem_stalled;
        wire    mem_ce, mem_stalled;
`ifdef  OPT_PIPELINED_BUS_ACCESS
`ifdef  OPT_PIPELINED_BUS_ACCESS
Line 474... Line 474...
        //      through the ALU.  Break instructions are not allowed through
        //      through the ALU.  Break instructions are not allowed through
        //      the ALU.
        //      the ALU.
`ifdef  OPT_PIPELINED
`ifdef  OPT_PIPELINED
        assign  alu_stall = (((~master_ce)||(mem_rdbusy)||(alu_busy))&&(opvalid_alu)) //Case 1&2
        assign  alu_stall = (((~master_ce)||(mem_rdbusy)||(alu_busy))&&(opvalid_alu)) //Case 1&2
                        ||((opvalid)&&(op_lock)&&(op_lock_stall))
                        ||((opvalid)&&(op_lock)&&(op_lock_stall))
                        ||((opvalid)&&(op_break))
                        ||((opvalid)&&(op_break))       // || op_illegal
                        ||(wr_reg_ce)&&(wr_write_cc)
                        ||(wr_reg_ce)&&(wr_write_cc)
                        ||(div_busy)||(fpu_busy);
                        ||(div_busy)||(fpu_busy);
        assign  alu_ce = (master_ce)&&(opvalid_alu)&&(~alu_stall)
        assign  alu_ce = (master_ce)&&(opvalid_alu)&&(~alu_stall)
                                &&(~clear_pipeline);
                                &&(~clear_pipeline);
`else
`else
        assign  alu_stall = (opvalid_alu)&&((~master_ce)||(op_break));
        assign  alu_stall = (opvalid_alu)&&((~master_ce)||(op_break));
        assign  alu_ce = (master_ce)&&((opvalid_alu)||(op_illegal))&&(~alu_stall)&&(~clear_pipeline);
        assign  alu_ce = (master_ce)&&(opvalid_alu)&&(~alu_stall)&&(~clear_pipeline);
`endif
`endif
        //
        //
 
 
        //
        //
        // Note: if you change the conditions for mem_ce, you must also change
        // Note: if you change the conditions for mem_ce, you must also change
Line 848... Line 848...
        initial opvalid_alu = 1'b0;
        initial opvalid_alu = 1'b0;
        initial opvalid_mem = 1'b0;
        initial opvalid_mem = 1'b0;
        initial opvalid_div = 1'b0;
        initial opvalid_div = 1'b0;
        initial opvalid_fpu = 1'b0;
        initial opvalid_fpu = 1'b0;
        always @(posedge i_clk)
        always @(posedge i_clk)
                if (i_rst)
                if ((i_rst)||(clear_pipeline))
                begin
                begin
                        opvalid     <= 1'b0;
                        opvalid     <= 1'b0;
                        opvalid_alu <= 1'b0;
                        opvalid_alu <= 1'b0;
                        opvalid_mem <= 1'b0;
                        opvalid_mem <= 1'b0;
                        opvalid_div <= 1'b0;
                        opvalid_div <= 1'b0;
Line 877... Line 877...
                        opvalid_alu <= (dcdALU)&&(w_opvalid);
                        opvalid_alu <= (dcdALU)&&(w_opvalid);
                        opvalid_mem <= (dcdM)&&(w_opvalid);
                        opvalid_mem <= (dcdM)&&(w_opvalid);
                        opvalid_div <= (dcdDV)&&(w_opvalid);
                        opvalid_div <= (dcdDV)&&(w_opvalid);
                        opvalid_fpu <= (dcdFP)&&(w_opvalid);
                        opvalid_fpu <= (dcdFP)&&(w_opvalid);
`endif
`endif
                end else if ((clear_pipeline)||(adf_ce_unconditional)||(mem_ce))
                end else if ((adf_ce_unconditional)||(mem_ce))
                begin
                begin
                        opvalid     <= 1'b0;
                        opvalid     <= 1'b0;
                        opvalid_alu <= 1'b0;
                        opvalid_alu <= 1'b0;
                        opvalid_mem <= 1'b0;
                        opvalid_mem <= 1'b0;
                        opvalid_div <= 1'b0;
                        opvalid_div <= 1'b0;
Line 901... Line 901...
        reg     r_op_break;
        reg     r_op_break;
 
 
        initial r_op_break = 1'b0;
        initial r_op_break = 1'b0;
        always @(posedge i_clk)
        always @(posedge i_clk)
                if (i_rst)      r_op_break <= 1'b0;
                if (i_rst)      r_op_break <= 1'b0;
                else if (op_ce) r_op_break <= (dcd_break); // &&(dcdvalid)
                else if (op_ce) r_op_break <= (dcd_break); //||dcd_illegal &&(dcdvalid)
                else if ((clear_pipeline)||(~opvalid))
                else if ((clear_pipeline)||(~opvalid))
                                r_op_break <= 1'b0;
                                r_op_break <= 1'b0;
        assign  op_break = r_op_break;
        assign  op_break = r_op_break;
`else
`else
        assign  op_break = dcd_break;
        assign  op_break = dcd_break;
Line 1130... Line 1130...
        //
        //
        //
        //
        //      PIPELINE STAGE #4 :: Apply Instruction
        //      PIPELINE STAGE #4 :: Apply Instruction
        //
        //
        //
        //
`ifdef  OPT_NEW_INSTRUCTION_SET
        cpuops  #(IMPLEMENT_MPY) doalu(i_clk, (i_rst)||(clear_pipeline),
        cpuops  #(IMPLEMENT_MPY) doalu(i_clk, i_rst, alu_ce,
                        alu_ce, opn, opA, opB,
                        (opvalid_alu), opn, opA, opB,
                        alu_result, alu_flags, alu_valid, alu_busy);
                        alu_result, alu_flags, alu_valid, alu_illegal_op,
 
                        alu_busy);
 
`else
 
        cpuops_deprecated       #(IMPLEMENT_MPY) doalu(i_clk, i_rst, alu_ce,
 
                        (opvalid_alu), opn, opA, opB,
 
                        alu_result, alu_flags, alu_valid, alu_illegal_op);
 
        assign  alu_busy = 1'b0;
 
`endif
 
 
 
        generate
        generate
        if (IMPLEMENT_DIVIDE != 0)
        if (IMPLEMENT_DIVIDE != 0)
        begin
        begin
                div thedivide(i_clk, (i_rst)||(clear_pipeline), div_ce, opn[0],
                div thedivide(i_clk, (i_rst)||(clear_pipeline), div_ce, opn[0],
Line 1265... Line 1257...
                        r_alu_illegal <= 1'b0;
                        r_alu_illegal <= 1'b0;
                else if (alu_ce)
                else if (alu_ce)
                        r_alu_illegal <= op_illegal;
                        r_alu_illegal <= op_illegal;
                else
                else
                        r_alu_illegal <= 1'b0;
                        r_alu_illegal <= 1'b0;
        assign  alu_illegal = (alu_illegal_op)||(r_alu_illegal);
        assign  alu_illegal = (r_alu_illegal);
`else
`else
        assign  alu_illegal = 1'b0;
        assign  alu_illegal = 1'b0;
`endif
`endif
 
 
        initial r_alu_pc_valid = 1'b0;
        initial r_alu_pc_valid = 1'b0;
Line 1467... Line 1459...
        initial r_break_pending = 1'b0;
        initial r_break_pending = 1'b0;
        always @(posedge i_clk)
        always @(posedge i_clk)
                if ((i_rst)||(clear_pipeline)||(~opvalid))
                if ((i_rst)||(clear_pipeline)||(~opvalid))
                        r_break_pending <= 1'b0;
                        r_break_pending <= 1'b0;
                else if (op_break)
                else if (op_break)
                        r_break_pending <= (~alu_busy)&&(~div_busy)&&(~fpu_busy)&&(~mem_busy);
                        r_break_pending <= (~alu_busy)&&(~div_busy)&&(~fpu_busy)&&(~mem_busy)&&(!wr_reg_ce);
                else
                else
                        r_break_pending <= 1'b0;
                        r_break_pending <= 1'b0;
        assign  break_pending = r_break_pending;
        assign  break_pending = r_break_pending;
`else
`else
        assign  break_pending = op_break;
        assign  break_pending = op_break;
Line 1481... Line 1473...
        assign  o_break = ((break_en)||(~op_gie))&&(break_pending)
        assign  o_break = ((break_en)||(~op_gie))&&(break_pending)
                                &&(~clear_pipeline)
                                &&(~clear_pipeline)
                        ||((~alu_gie)&&(bus_err))
                        ||((~alu_gie)&&(bus_err))
                        ||((~alu_gie)&&(div_error))
                        ||((~alu_gie)&&(div_error))
                        ||((~alu_gie)&&(fpu_error))
                        ||((~alu_gie)&&(fpu_error))
                        ||((~alu_gie)&&(alu_illegal));
                        ||((~alu_gie)&&(alu_illegal)&&(!clear_pipeline));
 
 
        // The sleep register.  Setting the sleep register causes the CPU to
        // The sleep register.  Setting the sleep register causes the CPU to
        // sleep until the next interrupt.  Setting the sleep register within
        // sleep until the next interrupt.  Setting the sleep register within
        // interrupt mode causes the processor to halt until a reset.  This is
        // interrupt mode causes the processor to halt until a reset.  This is
        // a panic/fault halt.  The trick is that you cannot be allowed to
        // a panic/fault halt.  The trick is that you cannot be allowed to
Line 1511... Line 1503...
                        // to sleep mode *and* supervisor mode at the same
                        // to sleep mode *and* supervisor mode at the same
                        // time, lest you halt the CPU.
                        // time, lest you halt the CPU.
                        sleep <= wr_spreg_vl[`CPU_SLEEP_BIT];
                        sleep <= wr_spreg_vl[`CPU_SLEEP_BIT];
 
 
        always @(posedge i_clk)
        always @(posedge i_clk)
                if ((i_rst)||(w_switch_to_interrupt))
                if (i_rst)
                        step <= 1'b0;
                        step <= 1'b0;
                else if ((wr_reg_ce)&&(~alu_gie)&&(wr_write_ucc))
                else if ((wr_reg_ce)&&(~alu_gie)&&(wr_write_ucc))
                        step <= wr_spreg_vl[`CPU_STEP_BIT];
                        step <= wr_spreg_vl[`CPU_STEP_BIT];
                else if (((alu_pc_valid)||(mem_pc_valid))&&(step)&&(gie))
 
                        step <= 1'b0;
 
 
 
        // The GIE register.  Only interrupts can disable the interrupt register
        // The GIE register.  Only interrupts can disable the interrupt register
        assign  w_switch_to_interrupt = (gie)&&(
        assign  w_switch_to_interrupt = (gie)&&(
                        // On interrupt (obviously)
                        // On interrupt (obviously)
                        ((i_interrupt)&&(~alu_phase)&&(~bus_lock))
                        ((i_interrupt)&&(~alu_phase)&&(~bus_lock))
Line 1529... Line 1519...
                        // If we encounter a break instruction, if the break
                        // If we encounter a break instruction, if the break
                        //      enable isn't set.
                        //      enable isn't set.
                        ||((master_ce)&&(break_pending)&&(~break_en))
                        ||((master_ce)&&(break_pending)&&(~break_en))
`ifdef  OPT_ILLEGAL_INSTRUCTION
`ifdef  OPT_ILLEGAL_INSTRUCTION
                        // On an illegal instruction
                        // On an illegal instruction
                        ||(alu_illegal)
                        ||((alu_illegal)&&(!clear_pipeline))
`endif
`endif
                        // On division by zero.  If the divide isn't
                        // On division by zero.  If the divide isn't
                        // implemented, div_valid and div_error will be short
                        // implemented, div_valid and div_error will be short
                        // circuited and that logic will be bypassed
                        // circuited and that logic will be bypassed
                        ||(div_error)
                        ||(div_error)
Line 1586... Line 1576...
                if (i_rst)
                if (i_rst)
                        ill_err_i <= 1'b0;
                        ill_err_i <= 1'b0;
                // Only the debug interface can clear this bit
                // Only the debug interface can clear this bit
                else if ((dbgv)&&(wr_write_scc))
                else if ((dbgv)&&(wr_write_scc))
                        ill_err_i <= (ill_err_i)&&(wr_spreg_vl[`CPU_ILL_BIT]);
                        ill_err_i <= (ill_err_i)&&(wr_spreg_vl[`CPU_ILL_BIT]);
                else if ((alu_illegal)&&(~alu_gie))
                else if ((alu_illegal)&&(~alu_gie)&&(!clear_pipeline))
                        ill_err_i <= 1'b1;
                        ill_err_i <= 1'b1;
        initial ill_err_u = 1'b0;
        initial ill_err_u = 1'b0;
        always @(posedge i_clk)
        always @(posedge i_clk)
                // The bit is automatically cleared on release from interrupt
                // The bit is automatically cleared on release from interrupt
                // or reset
                // or reset
Line 1598... Line 1588...
                        ill_err_u <= 1'b0;
                        ill_err_u <= 1'b0;
                // If the supervisor (or debugger) writes to this register,
                // If the supervisor (or debugger) writes to this register,
                // clearing the bit, then clear it
                // clearing the bit, then clear it
                else if (((~alu_gie)||(dbgv))&&(wr_reg_ce)&&(wr_write_ucc))
                else if (((~alu_gie)||(dbgv))&&(wr_reg_ce)&&(wr_write_ucc))
                        ill_err_u <=((ill_err_u)&&(wr_spreg_vl[`CPU_ILL_BIT]));
                        ill_err_u <=((ill_err_u)&&(wr_spreg_vl[`CPU_ILL_BIT]));
                else if ((alu_illegal)&&(alu_gie))
                else if ((alu_illegal)&&(alu_gie)&&(!clear_pipeline))
                        ill_err_u <= 1'b1;
                        ill_err_u <= 1'b1;
`else
`else
        assign ill_err_u = 1'b0;
        assign ill_err_u = 1'b0;
        assign ill_err_i = 1'b0;
        assign ill_err_i = 1'b0;
`endif
`endif
Line 1732... Line 1722...
        // a non-gie instruction?
        // a non-gie instruction?
        always @(posedge i_clk)
        always @(posedge i_clk)
                if ((wr_reg_ce)&&(wr_reg_id[4])&&(wr_write_pc))
                if ((wr_reg_ce)&&(wr_reg_id[4])&&(wr_write_pc))
                        upc <= wr_spreg_vl[(AW-1):0];
                        upc <= wr_spreg_vl[(AW-1):0];
                else if ((alu_gie)&&
                else if ((alu_gie)&&
                                (((alu_pc_valid)&&(~clear_pipeline))
                                (((alu_pc_valid)&&(~clear_pipeline)&&(!alu_illegal))
                                ||(mem_pc_valid)))
                                ||(mem_pc_valid)))
                        upc <= alu_pc;
                        upc <= alu_pc;
 
 
        always @(posedge i_clk)
        always @(posedge i_clk)
                if (i_rst)
                if (i_rst)

powered by: WebSVN 2.1.0

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