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

Subversion Repositories zipcpu

[/] [zipcpu/] [trunk/] [rtl/] [core/] [zipcpu.v] - Diff between revs 71 and 83

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

Rev 71 Rev 83
Line 201... Line 201...
        reg     [31:0]   regset [0:31];
        reg     [31:0]   regset [0:31];
 
 
        // Condition codes
        // Condition codes
        // (BUS, TRAP,ILL,BREAKEN,STEP,GIE,SLEEP ), V, N, C, Z
        // (BUS, TRAP,ILL,BREAKEN,STEP,GIE,SLEEP ), V, N, C, Z
        reg     [3:0]    flags, iflags;
        reg     [3:0]    flags, iflags;
        wire    [12:0]   w_uflags, w_iflags;
        wire    [13:0]   w_uflags, w_iflags;
        reg             trap, break_en, step, gie, sleep;
        reg             trap, break_en, step, gie, sleep;
`ifdef  OPT_ILLEGAL_INSTRUCTION
`ifdef  OPT_ILLEGAL_INSTRUCTION
        reg             ill_err_u, ill_err_i;
        reg             ill_err_u, ill_err_i;
`else
`else
        wire            ill_err_u, ill_err_i;
        wire            ill_err_u, ill_err_i;
Line 240... Line 240...
        //
        //
        //      PIPELINE STAGE #2 :: Instruction Decode
        //      PIPELINE STAGE #2 :: Instruction Decode
        //              Variable declarations
        //              Variable declarations
        //
        //
        //
        //
        reg             opvalid, opvalid_mem, opvalid_alu, op_wr_pc;
        reg             opvalid, opvalid_mem, opvalid_alu;
        reg             opvalid_div, opvalid_fpu;
        reg             opvalid_div, opvalid_fpu;
        wire            op_stall, dcd_ce, dcd_phase;
        wire            op_stall, dcd_ce, dcd_phase;
        wire    [3:0]    dcdOp;
        wire    [3:0]    dcdOp;
        wire    [4:0]    dcdA, dcdB, dcdR;
        wire    [4:0]    dcdA, dcdB, dcdR;
        wire            dcdA_cc, dcdB_cc, dcdA_pc, dcdB_pc, dcdR_cc, dcdR_pc;
        wire            dcdA_cc, dcdB_cc, dcdA_pc, dcdB_pc, dcdR_cc, dcdR_pc;
Line 279... Line 279...
        reg     [31:0]   r_opA, r_opB;
        reg     [31:0]   r_opA, r_opB;
        reg     [(AW-1):0]       op_pc;
        reg     [(AW-1):0]       op_pc;
        wire    [31:0]   w_opA, w_opB;
        wire    [31:0]   w_opA, w_opB;
        wire    [31:0]   opA_nowait, opB_nowait, opA, opB;
        wire    [31:0]   opA_nowait, opB_nowait, opA, opB;
        reg             opR_wr, opR_cc, opF_wr, op_gie;
        reg             opR_wr, opR_cc, opF_wr, op_gie;
        wire    [12:0]   opFl;
        wire    [13:0]   opFl;
        reg     [5:0]    r_opF;
        reg     [5:0]    r_opF;
        wire    [7:0]    opF;
        wire    [7:0]    opF;
        reg     [2:0]    opF_cp;
 
        wire            op_ce, op_phase;
        wire            op_ce, op_phase;
        // Some pipeline control wires
        // Some pipeline control wires
`ifdef  OPT_PIPELINED
`ifdef  OPT_PIPELINED
        reg     opA_alu, opA_mem;
        reg     opA_alu, opA_mem;
        reg     opB_alu, opB_mem;
        reg     opB_alu, opB_mem;
Line 402... Line 401...
                        // Stall if going into the ALU and the ALU is stalled
                        // Stall if going into the ALU and the ALU is stalled
                        //      i.e. if the memory is busy, or we are single
                        //      i.e. if the memory is busy, or we are single
                        //      stepping.  This also includes our stalls for
                        //      stepping.  This also includes our stalls for
                        //      op_break and op_lock, so we don't need to
                        //      op_break and op_lock, so we don't need to
                        //      include those as well here.
                        //      include those as well here.
                        ((opvalid)&&(alu_stall))
                        // This also includes whether or not the divide or
                        // Stall if the divide is busy, since we can't have
                        // floating point units are busy.
                        // two parallel stages writing back at the same time
                        (alu_stall)
                        ||(div_busy)
 
                        // Same for the floating point unit
 
                        ||(fpu_busy)
 
                        //
                        //
                        // ||((opvalid_alu)&&(mem_rdbusy)) // part of alu_stall
 
                        // Stall if we are going into memory with an operation
                        // Stall if we are going into memory with an operation
                        //      that cannot be pipelined, and the memory is
                        //      that cannot be pipelined, and the memory is
                        //      already busy
                        //      already busy
                        ||((opvalid_mem)&&(mem_stalled))
                        ||(mem_stalled) // &&(opvalid_mem) part of mem_stalled
                        // ||((opvalid_mem)&&(dcdvalid)&&(dcdM)&&(~dcd_pipe))
 
                        )
                        )
                        ||(dcdvalid)&&(
                        ||(dcdvalid)&&(
                                // Stall if we need to wait for an operand A
                                // Stall if we need to wait for an operand A
                                // to be ready to read
                                // to be ready to read
                                (dcdA_stall)
                                (dcdA_stall)
Line 665... Line 659...
                        if ((wr_reg_ce)&&(wr_reg_id == dcdA))
                        if ((wr_reg_ce)&&(wr_reg_id == dcdA))
                                r_opA <= wr_reg_vl;
                                r_opA <= wr_reg_vl;
                        else if (dcdA_pc)
                        else if (dcdA_pc)
                                r_opA <= w_pcA_v;
                                r_opA <= w_pcA_v;
                        else if (dcdA_cc)
                        else if (dcdA_cc)
                                r_opA <= { w_opA[31:13], (dcdA[4])?w_uflags:w_iflags };
                                r_opA <= { w_opA[31:14], (dcdA[4])?w_uflags:w_iflags };
                        else
                        else
                                r_opA <= w_opA;
                                r_opA <= w_opA;
`ifdef  OPT_PIPELINED
`ifdef  OPT_PIPELINED
                end else
                end else
                begin // We were going to pick these up when they became valid,
                begin // We were going to pick these up when they became valid,
Line 691... Line 685...
        endgenerate
        endgenerate
 
 
        assign  w_opBnI = (~dcdB_rd) ? 32'h00
        assign  w_opBnI = (~dcdB_rd) ? 32'h00
                : (((wr_reg_ce)&&(wr_reg_id == dcdB)) ? wr_reg_vl
                : (((wr_reg_ce)&&(wr_reg_id == dcdB)) ? wr_reg_vl
                : ((dcdB_pc) ? w_pcB_v
                : ((dcdB_pc) ? w_pcB_v
                : ((dcdB_cc) ? { w_opB[31:13], (dcdB[4])?w_uflags:w_iflags}
                : ((dcdB_cc) ? { w_opB[31:14], (dcdB[4])?w_uflags:w_iflags}
                : w_opB)));
                : w_opB)));
 
 
        always @(posedge i_clk)
        always @(posedge i_clk)
                if (op_ce) // &&(dcdvalid))
                if (op_ce) // &&(dcdvalid))
                        r_opB <= w_opBnI + dcdI;
                        r_opB <= w_opBnI + dcdI;
Line 738... Line 732...
                        3'h6:   r_opF <= 6'h02; // C
                        3'h6:   r_opF <= 6'h02; // C
                        3'h7:   r_opF <= 6'h08; // V
                        3'h7:   r_opF <= 6'h08; // V
                        endcase
                        endcase
                end // Bit order is { (flags_not_used), VNCZ mask, VNCZ value }
                end // Bit order is { (flags_not_used), VNCZ mask, VNCZ value }
        assign  opF = { r_opF[3], r_opF[5], r_opF[1], r_opF[4:0] };
        assign  opF = { r_opF[3], r_opF[5], r_opF[1], r_opF[4:0] };
        always @(posedge i_clk)
 
                if (op_ce)
 
                        opF_cp[2:0] <= dcdF[2:0];
 
 
 
        wire    w_opvalid;
        wire    w_opvalid;
        assign  w_opvalid = (~clear_pipeline)&&(dcdvalid);
        assign  w_opvalid = (~clear_pipeline)&&(dcdvalid);
        initial opvalid     = 1'b0;
        initial opvalid     = 1'b0;
        initial opvalid_alu = 1'b0;
        initial opvalid_alu = 1'b0;
Line 855... Line 846...
        // set, dcd_early_branch will simply be a wire connected to zero and
        // set, dcd_early_branch will simply be a wire connected to zero and
        // this logic should just optimize.
        // this logic should just optimize.
        always @(posedge i_clk)
        always @(posedge i_clk)
                if (op_ce)
                if (op_ce)
                begin
                begin
                        opF_wr <= (dcdF_wr)&&((~dcdR_cc)||(~dcdR_wr))&&(~dcd_early_branch);
                        opF_wr <= (dcdF_wr)&&((~dcdR_cc)||(~dcdR_wr))
                        opR_wr <= (dcdR_wr)&&(~dcd_early_branch);
                                &&(~dcd_early_branch)&&(~dcd_illegal);
                        op_wr_pc <= ((dcdR_wr)&&(dcdR_pc)
                        opR_wr <= (dcdR_wr)&&(~dcd_early_branch)&&(~dcd_illegal);
                                        &&(dcdR[4] == dcd_gie))
 
                                        &&(~dcd_early_branch);
 
                end
                end
 
 
        always @(posedge i_clk)
        always @(posedge i_clk)
                if (op_ce)
                if (op_ce)
                begin
                begin
Line 905... Line 894...
        // op_stall wire, which would stall any upstream stage.
        // op_stall wire, which would stall any upstream stage.
        // We'll create a flag here to start our coordination.  Once we
        // We'll create a flag here to start our coordination.  Once we
        // define this flag to something other than just plain zero, then
        // define this flag to something other than just plain zero, then
        // the stalls will already be in place.
        // the stalls will already be in place.
`ifdef  OPT_PIPELINED
`ifdef  OPT_PIPELINED
        assign  opA = ((wr_reg_ce)&&(wr_reg_id == opA_id)&&(opA_rd))
        assign  opA = ((wr_reg_ce)&&(wr_reg_id == opA_id)) // &&(opA_rd))
                        ?  wr_reg_vl : r_opA;
                        ?  wr_reg_vl : r_opA;
`else
`else
        assign  opA = r_opA;
        assign  opA = r_opA;
`endif
`endif
 
 
`ifdef  OPT_PIPELINED
`ifdef  OPT_PIPELINED
        assign  dcdA_stall = (dcdvalid)&&(dcdA_rd)&&(
        // Stall if we have decoded an instruction that will read register A
                                ((opvalid_alu)&&(opF_wr)&&(dcdA_cc))
        //      AND ... something that may write a register is running
                                );
        //      AND (series of conditions here ...)
 
        //              The operation might set flags, and we wish to read the
 
        //                      CC register
 
        //              OR ... (No other conditions)
 
        assign  dcdA_stall = (dcdA_rd) // &&(dcdvalid) is checked for elsewhere
 
                                &&((opvalid)||(mem_rdbusy)
 
                                        ||(div_busy)||(fpu_busy))
 
                                &&((opF_wr)&&(dcdA_cc));
`else
`else
        // There are no pipeline hazards, if we aren't pipelined
        // There are no pipeline hazards, if we aren't pipelined
        assign  dcdA_stall = 1'b0;
        assign  dcdA_stall = 1'b0;
`endif
`endif
 
 
Line 928... Line 924...
`else
`else
        assign  opB = r_opB;
        assign  opB = r_opB;
`endif
`endif
 
 
`ifdef  OPT_PIPELINED
`ifdef  OPT_PIPELINED
        assign  dcdB_stall = (dcdvalid)&&(dcdB_rd)&&(
        // Stall if we have decoded an instruction that will read register B
 
        //      AND ... something that may write a (unknown) register is running
 
        //      AND (series of conditions here ...)
 
        //              The operation might set flags, and we wish to read the
 
        //                      CC register
 
        //              OR the operation might set register B, and we still need
 
        //                      a clock to add the offset to it
 
        assign  dcdB_stall = (dcdB_rd) // &&(dcdvalid) is checked for elsewhere
 
                                // If the op stage isn't valid, yet something
 
                                // is running, then it must have been valid.
 
                                // We'll use the last values from that stage
 
                                // (opR_wr, opF_wr, opR) in our logic below.
 
                                &&((opvalid)||(mem_rdbusy)
 
                                        ||(div_busy)||(fpu_busy))
 
                                &&(
                                // Stall on memory ops writing to my register
                                // Stall on memory ops writing to my register
                                //      (i.e. loads), or on any write to my
                                //      (i.e. loads), or on any write to my
                                //      register if I have an immediate offset
                                //      register if I have an immediate offset
                                // Note the exception for writing to the PC:
                                // Note the exception for writing to the PC:
                                //      if I write to the PC, the whole next
                                //      if I write to the PC, the whole next
                                //      instruction is invalid, not just the
                                //      instruction is invalid, not just the
                                //      operand.  That'll get wiped in the
                                //      operand.  That'll get wiped in the
                                //      next operation anyway, so don't stall
                                //      next operation anyway, so don't stall
                                //      here.
                                //      here.  This keeps a BC X, BNZ Y from
                                ((~dcd_zI)&&(dcdB_rd)&&(opR == dcdB)&&(opR_wr)
                                //      stalling between the two branches.
                                        &&(opR != { op_gie, `CPU_PC_REG } )
                                //      BC X, BRA Y is still clear, since BRA Y
                                        &&((opvalid)||(mem_rdbusy)
                                //      is an early branch instruction.
                                                ||(div_busy)||(fpu_busy)))
                                //      (This exception is commented out in
                                // Stall on any write to the flags register,
                                //      order to help keep our logic simple, and
                                // if we're going to need the flags value for
                                //      because multiple conditional branches
                                // opB.
                                //      following each other constitutes a
                                ||((opvalid_alu)&&(opF_wr)&&(dcdB_cc))
                                //      fairly unusualy code structure.)
 
                                //      
 
                                ((~dcd_zI)&&(opR == dcdB)&&(opR_wr))
 
                                        // &&(opR != { op_gie, `CPU_PC_REG } )
 
                                // Stall following any instruction that will
 
                                // set the flags, if we're going to need the
 
                                // flags (CC) register for opB.
 
                                ||((opF_wr)&&(dcdB_cc))
                                // Stall on any ongoing memory operation that
                                // Stall on any ongoing memory operation that
                                // will write to opB -- captured above
                                // will write to opB -- captured above
                                // ||((mem_busy)&&(~mem_we)&&(mem_last_reg==dcdB)&&(~dcd_zI))
                                // ||((mem_busy)&&(~mem_we)&&(mem_last_reg==dcdB)&&(~dcd_zI))
                                );
                                );
`else
`else
        // No stalls without pipelining, 'cause how can you have a pipeline
        // No stalls without pipelining, 'cause how can you have a pipeline
        // hazard without the pipeline?
        // hazard without the pipeline?
        assign  dcdB_stall = 1'b0;
        assign  dcdB_stall = 1'b0;
`endif
`endif
        assign  dcdF_stall = (dcdvalid)&&((~dcdF[3])
        assign  dcdF_stall = ((~dcdF[3])
                                        ||((dcdA_rd)&&(dcdA_cc))
                                        ||((dcdA_rd)&&(dcdA_cc))
                                        ||((dcdB_rd)&&(dcdB_cc)))
                                        ||((dcdB_rd)&&(dcdB_cc)))
                                        &&(opvalid)&&(opR_cc);
                                        &&(opvalid)&&(opR_cc);
 
                                // &&(dcdvalid) is checked for elsewhere
        //
        //
        //
        //
        //      PIPELINE STAGE #4 :: Apply Instruction
        //      PIPELINE STAGE #4 :: Apply Instruction
        //
        //
        //
        //
Line 979... Line 997...
`endif
`endif
 
 
        generate
        generate
        if (IMPLEMENT_DIVIDE != 0)
        if (IMPLEMENT_DIVIDE != 0)
        begin
        begin
                div thedivide(i_clk, i_rst, div_ce, opn[0],
                div thedivide(i_clk, (i_rst)||(clear_pipeline), div_ce, opn[0],
                        opA, opB, div_busy, div_valid, div_error, div_result,
                        opA, opB, div_busy, div_valid, div_error, div_result,
                        div_flags);
                        div_flags);
        end else begin
        end else begin
                assign  div_error = 1'b1;
                assign  div_error = 1'b1;
                assign  div_busy  = 1'b0;
                assign  div_busy  = 1'b0;
Line 1163... Line 1181...
        //      Note that the flags needed to be checked before issuing the
        //      Note that the flags needed to be checked before issuing the
        //      bus instruction, so they don't need to be checked here.
        //      bus instruction, so they don't need to be checked here.
        //      Further, alu_wr includes (set_cond), so we don't need to
        //      Further, alu_wr includes (set_cond), so we don't need to
        //      check for that here either.
        //      check for that here either.
`ifdef  OPT_ILLEGAL_INSTRUCTION
`ifdef  OPT_ILLEGAL_INSTRUCTION
        assign  wr_reg_ce = (~alu_illegal)&&((alu_wr)&&(alu_valid)&&(~clear_pipeline))||(mem_valid)||(div_valid)||(fpu_valid);
        assign  wr_reg_ce = (~alu_illegal)&&
 
                        (((alu_wr)&&(~clear_pipeline)
 
                                &&((alu_valid)||(div_valid)||(fpu_valid)))
 
                        ||(mem_valid));
`else
`else
        assign  wr_reg_ce = ((alu_wr)&&(~clear_pipeline))||(mem_valid)||(div_valid)||(fpu_valid);
        assign  wr_reg_ce = ((alu_wr)&&(~clear_pipeline))||(mem_valid)||(div_valid)||(fpu_valid);
`endif
`endif
        // Which register shall be written?
        // Which register shall be written?
        //      COULD SIMPLIFY THIS: by adding three bits to these registers,
        //      COULD SIMPLIFY THIS: by adding three bits to these registers,
Line 1191... Line 1212...
        //
        //
        // Write back to the condition codes/flags register ...
        // Write back to the condition codes/flags register ...
        // When shall we write to our flags register?  alF_wr already
        // When shall we write to our flags register?  alF_wr already
        // includes the set condition ...
        // includes the set condition ...
        assign  wr_flags_ce = ((alF_wr)||(div_valid)||(fpu_valid))&&(~clear_pipeline)&&(~alu_illegal);
        assign  wr_flags_ce = ((alF_wr)||(div_valid)||(fpu_valid))&&(~clear_pipeline)&&(~alu_illegal);
        assign  w_uflags = { ufpu_err_flag,
        assign  w_uflags = { uhalt_phase, ufpu_err_flag,
                        udiv_err_flag, ubus_err_flag, trap, ill_err_u,
                        udiv_err_flag, ubus_err_flag, trap, ill_err_u,
                        1'b0, step, 1'b1, sleep,
                        1'b0, step, 1'b1, sleep,
                        ((wr_flags_ce)&&(alu_gie))?alu_flags:flags };
                        ((wr_flags_ce)&&(alu_gie))?alu_flags:flags };
        assign  w_iflags = { ifpu_err_flag,
        assign  w_iflags = { ihalt_phase, ifpu_err_flag,
                        idiv_err_flag, ibus_err_flag, trap, ill_err_i,
                        idiv_err_flag, ibus_err_flag, trap, ill_err_i,
                        break_en, 1'b0, 1'b0, sleep,
                        break_en, 1'b0, 1'b0, sleep,
                        ((wr_flags_ce)&&(~alu_gie))?alu_flags:iflags };
                        ((wr_flags_ce)&&(~alu_gie))?alu_flags:iflags };
 
 
 
 
Line 1565... Line 1586...
                        o_dbg_reg <= regset[i_dbg_reg];
                        o_dbg_reg <= regset[i_dbg_reg];
                        if (i_dbg_reg[3:0] == `CPU_PC_REG)
                        if (i_dbg_reg[3:0] == `CPU_PC_REG)
                                o_dbg_reg <= {{(32-AW){1'b0}},(i_dbg_reg[4])?upc:ipc};
                                o_dbg_reg <= {{(32-AW){1'b0}},(i_dbg_reg[4])?upc:ipc};
                        else if (i_dbg_reg[3:0] == `CPU_CC_REG)
                        else if (i_dbg_reg[3:0] == `CPU_CC_REG)
                        begin
                        begin
                                o_dbg_reg[12:0] <= (i_dbg_reg[4])?w_uflags:w_iflags;
                                o_dbg_reg[13:0] <= (i_dbg_reg[4])?w_uflags:w_iflags;
                                o_dbg_reg[`CPU_GIE_BIT] <= gie;
                                o_dbg_reg[`CPU_GIE_BIT] <= gie;
                        end
                        end
                end
                end
        end else begin
        end else begin
                always @(posedge i_clk)
                always @(posedge i_clk)
Line 1577... Line 1598...
                        o_dbg_reg <= regset[i_dbg_reg];
                        o_dbg_reg <= regset[i_dbg_reg];
                        if (i_dbg_reg[3:0] == `CPU_PC_REG)
                        if (i_dbg_reg[3:0] == `CPU_PC_REG)
                                o_dbg_reg <= (i_dbg_reg[4])?upc:ipc;
                                o_dbg_reg <= (i_dbg_reg[4])?upc:ipc;
                        else if (i_dbg_reg[3:0] == `CPU_CC_REG)
                        else if (i_dbg_reg[3:0] == `CPU_CC_REG)
                        begin
                        begin
                                o_dbg_reg[12:0] <= (i_dbg_reg[4])?w_uflags:w_iflags;
                                o_dbg_reg[13:0] <= (i_dbg_reg[4])?w_uflags:w_iflags;
                                o_dbg_reg[`CPU_GIE_BIT] <= gie;
                                o_dbg_reg[`CPU_GIE_BIT] <= gie;
                        end
                        end
                end
                end
        end endgenerate
        end endgenerate
 
 

powered by: WebSVN 2.1.0

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