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

Subversion Repositories zipcpu

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

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

Rev 69 Rev 71
Line 139... Line 139...
`ifdef  OPT_MULTIPLY
`ifdef  OPT_MULTIPLY
        parameter       IMPLEMENT_MPY = 1;
        parameter       IMPLEMENT_MPY = 1;
`else
`else
        parameter       IMPLEMENT_MPY = 0;
        parameter       IMPLEMENT_MPY = 0;
`endif
`endif
        parameter       IMPLEMENT_DIVIDE = 1, IMPLEMENT_FPU = 0,
`ifdef  OPT_DIVIDE
 
        parameter       IMPLEMENT_DIVIDE = 1;
 
`else
 
        parameter       IMPLEMENT_DIVIDE = 0;
 
`endif
 
`ifdef  OPT_IMPLEMENT_FPU
 
        parameter       IMPLEMENT_FPU = 1,
 
`else
 
        parameter       IMPLEMENT_FPU = 0,
 
`endif
                        IMPLEMENT_LOCK=1;
                        IMPLEMENT_LOCK=1;
`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;
Line 240... Line 249...
        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;
        wire    [3:0]    dcdF;
        wire    [3:0]    dcdF;
        wire            dcdR_wr, dcdA_rd, dcdB_rd,
        wire            dcdR_wr, dcdA_rd, dcdB_rd,
                                dcdALU, dcdM, dcdDV, dcdFP,
                                dcdALU, dcdM, dcdDV, dcdFP,
                                dcdF_wr, dcd_gie, dcd_break, dcd_lock;
                                dcdF_wr, dcd_gie, dcd_break, dcd_lock,
 
                                dcd_pipe;
        reg             r_dcdvalid;
        reg             r_dcdvalid;
        wire            dcdvalid;
        wire            dcdvalid;
        wire    [(AW-1):0]       dcd_pc;
        wire    [(AW-1):0]       dcd_pc;
        wire    [31:0]   dcdI;
        wire    [31:0]   dcdI;
        wire            dcd_zI; // true if dcdI == 0
        wire            dcd_zI; // true if dcdI == 0
Line 298... Line 308...
        reg             alu_pc_valid;
        reg             alu_pc_valid;
        wire            alu_phase;
        wire            alu_phase;
        wire            alu_ce, alu_stall;
        wire            alu_ce, alu_stall;
        wire    [31:0]   alu_result;
        wire    [31:0]   alu_result;
        wire    [3:0]    alu_flags;
        wire    [3:0]    alu_flags;
        wire            alu_valid;
        wire            alu_valid, alu_busy;
        wire            set_cond;
        wire            set_cond;
        reg             alu_wr, alF_wr, alu_gie;
        reg             alu_wr, alF_wr, alu_gie;
        wire            alu_illegal_op;
        wire            alu_illegal_op;
        wire            alu_illegal;
        wire            alu_illegal;
 
 
Line 317... Line 327...
        wire    [4:0]            mem_wreg;
        wire    [4:0]            mem_wreg;
 
 
        wire                    mem_busy, mem_rdbusy;
        wire                    mem_busy, mem_rdbusy;
        wire    [(AW-1):0]       mem_addr;
        wire    [(AW-1):0]       mem_addr;
        wire    [31:0]           mem_data, mem_result;
        wire    [31:0]           mem_data, mem_result;
        reg     [4:0]            mem_last_reg; // Last register result to go in
 
 
 
        wire    div_ce, div_error, div_busy, div_valid;
        wire    div_ce, div_error, div_busy, div_valid;
        wire    [31:0]   div_result;
        wire    [31:0]   div_result;
        wire    [3:0]    div_flags;
        wire    [3:0]    div_flags;
 
 
Line 405... Line 414...
                        // ||((opvalid_alu)&&(mem_rdbusy)) // part of alu_stall
                        // ||((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))
                        ||((opvalid_mem)&&(mem_stalled))
 
                        // ||((opvalid_mem)&&(dcdvalid)&&(dcdM)&&(~dcd_pipe))
                        )
                        )
                        ||(dcdvalid)&&(
                        ||(dcdvalid)&&(
                                // Stall if we've got a read going with an
                                // Stall if we need to wait for an operand A
                                // unknown output (known w/in the memory module)
 
                                (mem_rdbusy)
 
                                // Or if we need to wait for an operand A
 
                                // to be ready to read
                                // to be ready to read
                                ||(dcdA_stall)
                                (dcdA_stall)
                                // Likewise for B, also includes logic
                                // Likewise for B, also includes logic
                                // regarding immediate offset (register must
                                // regarding immediate offset (register must
                                // be in register file if we need to add to
                                // be in register file if we need to add to
                                // an immediate)
                                // an immediate)
                                ||(dcdB_stall)
                                ||(dcdB_stall)
                                // Or if we need to wait on flags to work on the
                                // Or if we need to wait on flags to work on the
                                // CC register
                                // CC register
                                ||(dcdF_stall)
                                ||(dcdF_stall)
                        );
                        );
        assign  op_ce = (dcdvalid)&&((~opvalid)||(~op_stall))&&(~clear_pipeline);
        assign  op_ce = ((dcdvalid)||(dcd_illegal))&&(~op_stall)&&(~clear_pipeline);
`else
`else
        assign  op_stall = (opvalid)&&(~master_ce);
        assign  op_stall = (opvalid)&&(~master_ce);
        assign  op_ce = (dcdvalid);
        assign  op_ce = ((dcdvalid)||(dcd_illegal));
`endif
`endif
 
 
        //
        //
        //      PIPELINE STAGE #4 :: ALU / Memory
        //      PIPELINE STAGE #4 :: ALU / Memory
        //              Calculate stall conditions
        //              Calculate stall conditions
Line 442... Line 449...
        //      since we don't know if it'll put us to sleep or not.
        //      since we don't know if it'll put us to sleep or not.
        // 4. Last case: Stall if we would otherwise move a break instruction
        // 4. Last case: Stall if we would otherwise move a break instruction
        //      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))&&(opvalid_alu)) //Case 1&2
        assign  alu_stall = (((~master_ce)||(mem_rdbusy)||(alu_busy))&&(opvalid_alu)) //Case 1&2
                        // Old case #3--this isn't an ALU stall though ...
                        // Old case #3--this isn't an ALU stall though ...
                        ||((opvalid_alu)&&(wr_reg_ce)&&(wr_reg_id[4] == op_gie)
                        ||((opvalid_alu)&&(wr_reg_ce)&&(wr_reg_id[4] == op_gie)
                                &&(wr_write_cc)) // Case 3
                                &&(wr_write_cc)) // Case 3
                        ||((opvalid)&&(op_lock)&&(op_lock_stall))
                        ||((opvalid)&&(op_lock)&&(op_lock_stall))
                        ||((opvalid)&&(op_break))
                        ||((opvalid)&&(op_break))
                        ||(div_busy)||(fpu_busy);
                        ||(div_busy)||(fpu_busy);
        assign  alu_ce = (master_ce)&&(opvalid_alu)
        assign  alu_ce = (master_ce)&&((opvalid_alu)||(op_illegal))
                                &&(~alu_stall)
                                &&(~alu_stall)
                                &&(~clear_pipeline);
                                &&(~clear_pipeline);
`else
`else
        assign  alu_stall = ((~master_ce)&&(opvalid_alu))
        assign  alu_stall = ((~master_ce)&&(opvalid_alu))
                                ||((opvalid_alu)&&(op_break));
                                ||((opvalid_alu)&&(op_break));
        assign  alu_ce = (master_ce)&&(opvalid_alu)&&(~alu_stall);
        assign  alu_ce = (master_ce)&&((opvalid_alu)||(op_illegal))&&(~alu_stall);
`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
        // alu_pc_valid.
        // alu_pc_valid.
        //
        //
`ifdef  OPT_PIPELINED
`ifdef  OPT_PIPELINED
        assign  mem_ce = (master_ce)&&(opvalid_mem)&&(~mem_stalled)
        assign  mem_ce = (master_ce)&&(opvalid_mem)&&(~mem_stalled)
                        &&(~clear_pipeline)&&(set_cond);
                        &&(~clear_pipeline);
`else
`else
        // If we aren't pipelined, then no one will be changing what's in the
        // If we aren't pipelined, then no one will be changing what's in the
        // pipeline (i.e. clear_pipeline), while our only instruction goes
        // pipeline (i.e. clear_pipeline), while our only instruction goes
        // through the ... pipeline.
        // through the ... pipeline.
        assign  mem_ce = (master_ce)&&(opvalid_mem)
        assign  mem_ce = (master_ce)&&(opvalid_mem)&&(~mem_stalled);
                        &&(set_cond)&&(~mem_stalled);
 
`endif
`endif
`ifdef  OPT_PIPELINED_BUS_ACCESS
`ifdef  OPT_PIPELINED_BUS_ACCESS
        assign  mem_stalled = (~master_ce)||((opvalid_mem)&&(
        assign  mem_stalled = (~master_ce)||(alu_busy)||((opvalid_mem)&&(
                                (mem_pipe_stalled)
                                (mem_pipe_stalled)
                                ||((~op_pipe)&&(mem_busy))
                                ||((~op_pipe)&&(mem_busy))
                                ||(div_busy)
                                ||(div_busy)
                                ||(fpu_busy)
                                ||(fpu_busy)
                                // Stall waiting for flags to be valid
                                // Stall waiting for flags to be valid
Line 583... Line 589...
                        { dcdB_cc, dcdB_pc, dcdB },
                        { dcdB_cc, dcdB_pc, dcdB },
                        dcdI, dcd_zI, dcdF, dcdF_wr, dcdOp,
                        dcdI, dcd_zI, dcdF, dcdF_wr, dcdOp,
                        dcdALU, dcdM, dcdDV, dcdFP, dcd_break, dcd_lock,
                        dcdALU, dcdM, dcdDV, dcdFP, dcd_break, dcd_lock,
                        dcdR_wr,dcdA_rd, dcdB_rd,
                        dcdR_wr,dcdA_rd, dcdB_rd,
                        dcd_early_branch,
                        dcd_early_branch,
                        dcd_branch_pc);
                        dcd_branch_pc,
 
                        dcd_pipe);
`else
`else
        idecode_deprecated
        idecode_deprecated
                #(AW, IMPLEMENT_MPY, EARLY_BRANCHING, IMPLEMENT_DIVIDE,
                #(AW, IMPLEMENT_MPY, EARLY_BRANCHING, IMPLEMENT_DIVIDE,
                        IMPLEMENT_FPU)
                        IMPLEMENT_FPU)
                instruction_decoder(i_clk, (i_rst)||(clear_pipeline),
                instruction_decoder(i_clk, (i_rst)||(clear_pipeline),
Line 599... Line 606...
                        { dcdB_cc, dcdB_pc, dcdB },
                        { dcdB_cc, dcdB_pc, dcdB },
                        dcdI, dcd_zI, dcdF, dcdF_wr, dcdOp,
                        dcdI, dcd_zI, dcdF, dcdF_wr, dcdOp,
                        dcdALU, dcdM, dcdDV, dcdFP, dcd_break, dcd_lock,
                        dcdALU, dcdM, dcdDV, dcdFP, dcd_break, dcd_lock,
                        dcdR_wr,dcdA_rd, dcdB_rd,
                        dcdR_wr,dcdA_rd, dcdB_rd,
                        dcd_early_branch,
                        dcd_early_branch,
                        dcd_branch_pc);
                        dcd_branch_pc,
 
                        dcd_pipe);
`endif
`endif
 
 
`ifdef  OPT_PIPELINED_BUS_ACCESS
`ifdef  OPT_PIPELINED_BUS_ACCESS
        reg     [23:0]   r_opI;
 
        reg     [4:0]    op_B;
 
        reg             op_pipe;
        reg             op_pipe;
 
 
        initial op_pipe = 1'b0;
        initial op_pipe = 1'b0;
        // To be a pipeable operation, there must be 
        // To be a pipeable operation, there must be 
        //      two valid adjacent instructions
        //      two valid adjacent instructions
        //      Both must be memory instructions
        //      Both must be memory instructions
        //      Both must be writes, or both must be reads
        //      Both must be writes, or both must be reads
        //      Both operations must be to the same identical address,
        //      Both operations must be to the same identical address,
        //              or at least a single (one) increment above that address
        //              or at least a single (one) increment above that address
 
        //
 
        // However ... we need to know this before this clock, hence this is
 
        // calculated in the instruction decoder.
        always @(posedge i_clk)
        always @(posedge i_clk)
                if (op_ce)
                if (op_ce)
                        op_pipe <= (dcdvalid)&&(opvalid_mem)&&(dcdM) // Both mem
                        op_pipe <= dcd_pipe;
                                &&(dcdOp[0]==opn[0]) // Both Rd, or both Wr
 
                                &&(dcdB == op_B) // Same address register
 
                                &&((dcdF[2:0] == opF_cp) // Same condition
 
                                        ||(opF_cp == 3'h0)) // or no prev condition
 
                                &&((dcdI[23:0] == r_opI)||(dcdI[23:0]==r_opI+24'h1));
 
        always @(posedge i_clk)
 
                if (op_ce) // &&(dcdvalid))
 
                        r_opI <= dcdI[23:0];
 
        always @(posedge i_clk)
 
                if (op_ce) // &&(dcdvalid))
 
                        op_B <= dcdB;
 
`endif
`endif
 
 
        //
        //
        //
        //
        //      PIPELINE STAGE #3 :: Read Operands (Registers)
        //      PIPELINE STAGE #3 :: Read Operands (Registers)
Line 645... Line 643...
        if (AW < 32)
        if (AW < 32)
                assign  w_pcA_v = {{(32-AW){1'b0}}, (dcdA[4] == dcd_gie)?dcd_pc:upc };
                assign  w_pcA_v = {{(32-AW){1'b0}}, (dcdA[4] == dcd_gie)?dcd_pc:upc };
        else
        else
                assign  w_pcA_v = (dcdA[4] == dcd_gie)?dcd_pc:upc;
                assign  w_pcA_v = (dcdA[4] == dcd_gie)?dcd_pc:upc;
        endgenerate
        endgenerate
 
 
 
`ifdef  OPT_PIPELINED
 
        reg     [4:0]    opA_id, opB_id;
 
        reg             opA_rd, opB_rd;
 
        always @(posedge i_clk)
 
                if (op_ce)
 
                begin
 
                        opA_id <= dcdA;
 
                        opB_id <= dcdB;
 
                        opA_rd <= dcdA_rd;
 
                        opB_rd <= dcdB_rd;
 
                end
 
`endif
 
 
        always @(posedge i_clk)
        always @(posedge i_clk)
                if (op_ce) // &&(dcdvalid))
                if (op_ce) // &&(dcdvalid))
                begin
                begin
                        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;
Line 657... Line 669...
                        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:13], (dcdA[4])?w_uflags:w_iflags };
                        else
                        else
                                r_opA <= w_opA;
                                r_opA <= w_opA;
`ifdef  OPT_PIPELINED
`ifdef  OPT_PIPELINED
                end else if (opvalid)
                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,
                        // but for some reason we're stuck here as they became
                        // but for some reason we're stuck here as they became
                        // valid.  Pick them up now anyway
                        // valid.  Pick them up now anyway
                        if (((opA_alu)&&(alu_wr))||((opA_mem)&&(mem_valid)))
                        // if (((opA_alu)&&(alu_wr))||((opA_mem)&&(mem_valid)))
 
                                // r_opA <= wr_reg_vl;
 
                        if ((wr_reg_ce)&&(wr_reg_id == opA_id)&&(opA_rd))
                                r_opA <= wr_reg_vl;
                                r_opA <= wr_reg_vl;
`endif
`endif
                end
                end
 
 
        wire    [31:0]   w_opBnI, w_pcB_v;
        wire    [31:0]   w_opBnI, w_pcB_v;
Line 684... Line 698...
 
 
        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;
`ifdef  OPT_PIPELINED
`ifdef  OPT_PIPELINED
                else if ((opvalid)&&(
                else if ((wr_reg_ce)&&(opB_id == wr_reg_id)&&(opB_rd))
                                ((opB_alu)&&(alu_wr))
 
                                ||((opB_mem)&&(mem_valid))))
 
                        r_opB <= wr_reg_vl;
                        r_opB <= wr_reg_vl;
`endif
`endif
 
 
        // The logic here has become more complex than it should be, no thanks
        // The logic here has become more complex than it should be, no thanks
        // to Xilinx's Vivado trying to help.  The conditions are supposed to
        // to Xilinx's Vivado trying to help.  The conditions are supposed to
Line 825... Line 837...
        assign op_lock_stall = 1'b0;
        assign op_lock_stall = 1'b0;
        assign op_lock       = 1'b0;
        assign op_lock       = 1'b0;
`endif
`endif
 
 
`ifdef  OPT_ILLEGAL_INSTRUCTION
`ifdef  OPT_ILLEGAL_INSTRUCTION
 
        initial op_illegal = 1'b0;
        always @(posedge i_clk)
        always @(posedge i_clk)
                if(op_ce)
                if ((i_rst)||(clear_pipeline))
 
                        op_illegal <= 1'b0;
 
                else if(op_ce)
`ifdef  OPT_PIPELINED
`ifdef  OPT_PIPELINED
                        op_illegal <=(dcd_illegal)||((dcd_lock)&&(IMPLEMENT_LOCK == 0));
                        op_illegal <=(dcd_illegal)||((dcd_lock)&&(IMPLEMENT_LOCK == 0));
`else
`else
                        op_illegal <= (dcd_illegal)||(dcd_lock);
                        op_illegal <= (dcd_illegal)||(dcd_lock);
`endif
`endif
`endif
`endif
 
 
        generate
        // No generate on EARLY_BRANCHING here, since if EARLY_BRANCHING is not
        if (EARLY_BRANCHING > 0)
        // set, dcd_early_branch will simply be a wire connected to zero and
        begin
        // 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))&&(~dcd_early_branch);
                                opR_wr <= (dcdR_wr)&&(~dcd_early_branch);
                                opR_wr <= (dcdR_wr)&&(~dcd_early_branch);
                                op_wr_pc <= ((dcdR_wr)&&(dcdR_pc)
                                op_wr_pc <= ((dcdR_wr)&&(dcdR_pc)
                                                &&(dcdR[4] == dcd_gie))
                                                &&(dcdR[4] == dcd_gie))
                                                &&(~dcd_early_branch);
                                                &&(~dcd_early_branch);
                        end
                        end
        end else begin
 
                always @(posedge i_clk)
 
                        if (op_ce)
 
                        begin
 
                                // Will we write the flags/CC Register with
 
                                // our result?
 
                                opF_wr <= (dcdF_wr)&&((~dcdR_cc)||(~dcdR_wr));
 
                                // Will we be writing our results into a
 
                                // register?
 
                                opR_wr <= dcdR_wr;
 
                                op_wr_pc <= ((dcdR_wr)&&(dcdR_pc)
 
                                                &&(dcdR[4] == dcd_gie));
 
                        end
 
        end endgenerate
 
 
 
        always @(posedge i_clk)
        always @(posedge i_clk)
                if (op_ce)
                if (op_ce)
                begin
                begin
                        opn    <= dcdOp;        // Which ALU operation?
                        opn    <= dcdOp;        // Which ALU operation?
Line 904... Line 905...
        // 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
        initial opA_alu = 1'b0;
        assign  opA = ((wr_reg_ce)&&(wr_reg_id == opA_id)&&(opA_rd))
        always @(posedge i_clk)
                        ?  wr_reg_vl : r_opA;
                if (op_ce)
 
                        opA_alu <= (opvalid_alu)&&(opR == dcdA)&&(opR_wr)&&(dcdA_rd);
 
                else if ((opvalid)&&(opA_alu)&&(alu_valid))
 
                        opA_alu <= 1'b0;
 
        initial opA_mem = 1'b0;
 
        always @(posedge i_clk)
 
                if (op_ce)
 
                        opA_mem <= ((opvalid_mem)&&(opR == dcdA)&&(dcdA_rd)&&(~opn[0]))
 
                                ||((~opvalid)&&(mem_busy)&&(~mem_we)
 
                                        &&(mem_last_reg == dcdA)&&(dcdA_rd));
 
                else if ((opvalid)&&(opA_mem)&&(mem_valid))
 
                        opA_mem <= 1'b0;
 
`endif
 
 
 
        always @(posedge i_clk)
 
                if (mem_ce)
 
                        mem_last_reg <= opR;
 
`ifdef  OPT_PIPELINED
 
        assign  opA = ((opA_alu)&&(alu_wr)) ? alu_result
 
                        : ( ((opA_mem)&&(mem_valid))?mem_result
 
                        : 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)&&(
        assign  dcdA_stall = (dcdvalid)&&(dcdA_rd)&&(
                                ((opvalid_alu)&&(opF_wr)&&(dcdA_cc)));
                                ((opvalid_alu)&&(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
 
 
`ifdef  OPT_PIPELINED
`ifdef  OPT_PIPELINED
        always @(posedge i_clk)
        assign  opB = ((wr_reg_ce)&&(wr_reg_id == opB_id)&&(opB_rd))
                if (op_ce)
                        ? wr_reg_vl: r_opB;
                        opB_alu <= (opvalid_alu)&&(opR == dcdB)&&(opR_wr)&&(dcdB_rd)&&(dcd_zI);
 
        always @(posedge i_clk)
 
                if (op_ce)
 
                        opB_mem <= (dcd_zI)&&(dcdB_rd)&&(
 
                                ((opvalid_mem)&&(opR == dcdB)&&(~opn[0]))
 
                                ||((~opvalid)&&(mem_busy)&&(~mem_we)
 
                                        &&(mem_last_reg == dcdB)));
 
                else if ((opvalid)&&(opB_mem)&&(mem_valid))
 
                        opB_mem <= 1'b0;
 
        assign  opB = ((opB_alu)&&(alu_wr)) ? alu_result
 
                        : ( ((opB_mem)&&(mem_valid))?mem_result
 
                        : r_opB );
 
`else
`else
        assign  opB = r_opB;
        assign  opB = r_opB;
`endif
`endif
 
 
`ifdef  OPT_PIPELINED
`ifdef  OPT_PIPELINED
Line 969... Line 938...
                                //      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.
                                ((opvalid)&&(opR_wr)&&(opR == dcdB)
                                ((~dcd_zI)&&(dcdB_rd)&&(opR == dcdB)&&(opR_wr)
                                        &&(opR != { op_gie, `CPU_PC_REG} )
                                        &&(opR != { op_gie, `CPU_PC_REG} )
                                        &&(~dcd_zI))
                                        &&((opvalid)||(mem_rdbusy)
 
                                                ||(div_busy)||(fpu_busy)))
                                // Stall on any write to the flags register,
                                // Stall on any write to the flags register,
                                // if we're going to need the flags value for
                                // if we're going to need the flags value for
                                // opB.
                                // opB.
                                ||((opvalid_alu)&&(opF_wr)&&(dcdB_cc))
                                ||((opvalid_alu)&&(opF_wr)&&(dcdB_cc))
                                // Stall on any ongoing memory operation that
                                // Stall on any ongoing memory operation that
                                // will write to opB
                                // will write to opB -- captured above
                                ||((mem_busy)&&(~mem_we)&&(mem_last_reg==dcdB)));
                                // ||((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
Line 996... Line 967...
        //
        //
        //
        //
`ifdef  OPT_NEW_INSTRUCTION_SET
`ifdef  OPT_NEW_INSTRUCTION_SET
        cpuops  #(IMPLEMENT_MPY) doalu(i_clk, i_rst, alu_ce,
        cpuops  #(IMPLEMENT_MPY) doalu(i_clk, i_rst, alu_ce,
                        (opvalid_alu), opn, opA, opB,
                        (opvalid_alu), opn, opA, opB,
                        alu_result, alu_flags, alu_valid, alu_illegal_op);
                        alu_result, alu_flags, alu_valid, alu_illegal_op,
 
                        alu_busy);
`else
`else
        cpuops_deprecated       #(IMPLEMENT_MPY) doalu(i_clk, i_rst, alu_ce,
        cpuops_deprecated       #(IMPLEMENT_MPY) doalu(i_clk, i_rst, alu_ce,
                        (opvalid_alu), opn, opA, opB,
                        (opvalid_alu), opn, opA, opB,
                        alu_result, alu_flags, alu_valid, alu_illegal_op);
                        alu_result, alu_flags, alu_valid, alu_illegal_op);
 
        assign  alu_busy = 1'b0;
`endif
`endif
 
 
        generate
        generate
        if (IMPLEMENT_DIVIDE != 0)
        if (IMPLEMENT_DIVIDE != 0)
        begin
        begin
Line 1052... Line 1025...
                end else if (alu_ce)
                end else if (alu_ce)
                begin
                begin
                        // alu_reg <= opR;
                        // alu_reg <= opR;
                        alu_wr  <= (opR_wr)&&(set_cond);
                        alu_wr  <= (opR_wr)&&(set_cond);
                        alF_wr  <= (opF_wr)&&(set_cond);
                        alF_wr  <= (opF_wr)&&(set_cond);
                end else begin
                end else if (~alu_busy) begin
                        // These are strobe signals, so clear them if not
                        // These are strobe signals, so clear them if not
                        // set for any particular clock
                        // set for any particular clock
                        alu_wr <= (i_halt)&&(i_dbg_we);
                        alu_wr <= (i_halt)&&(i_dbg_we);
                        alF_wr <= 1'b0;
                        alF_wr <= 1'b0;
                end
                end
Line 1097... Line 1070...
 
 
`ifdef  OPT_ILLEGAL_INSTRUCTION
`ifdef  OPT_ILLEGAL_INSTRUCTION
        reg     r_alu_illegal;
        reg     r_alu_illegal;
        initial r_alu_illegal = 0;
        initial r_alu_illegal = 0;
        always @(posedge i_clk)
        always @(posedge i_clk)
                if ((alu_ce)||(mem_ce))
                if (clear_pipeline)
 
                        r_alu_illegal <= 1'b0;
 
                else if ((alu_ce)||(mem_ce))
                        r_alu_illegal <= op_illegal;
                        r_alu_illegal <= op_illegal;
        assign  alu_illegal = (alu_illegal_op)||(r_alu_illegal);
        assign  alu_illegal = (alu_illegal_op)||(r_alu_illegal);
`endif
`endif
 
 
        // This _almost_ is equal to (alu_ce)||(mem_ce).  The only
        // This _almost_ is equal to (alu_ce)||(mem_ce).  The only
Line 1134... Line 1109...
`else
`else
        assign  bus_lock = 1'b0;
        assign  bus_lock = 1'b0;
`endif
`endif
 
 
`ifdef  OPT_PIPELINED_BUS_ACCESS
`ifdef  OPT_PIPELINED_BUS_ACCESS
        pipemem #(AW,IMPLEMENT_LOCK) domem(i_clk, i_rst, mem_ce, bus_lock,
        pipemem #(AW,IMPLEMENT_LOCK) domem(i_clk, i_rst,(mem_ce)&&(set_cond), bus_lock,
                                (opn[0]), opB, opA, opR,
                                (opn[0]), opB, opA, opR,
                                mem_busy, mem_pipe_stalled,
                                mem_busy, mem_pipe_stalled,
                                mem_valid, bus_err, mem_wreg, mem_result,
                                mem_valid, bus_err, mem_wreg, mem_result,
                        mem_cyc_gbl, mem_cyc_lcl,
                        mem_cyc_gbl, mem_cyc_lcl,
                                mem_stb_gbl, mem_stb_lcl,
                                mem_stb_gbl, mem_stb_lcl,
                                mem_we, mem_addr, mem_data,
                                mem_we, mem_addr, mem_data,
                                mem_ack, mem_stall, mem_err, i_wb_data);
                                mem_ack, mem_stall, mem_err, i_wb_data);
 
 
`else // PIPELINED_BUS_ACCESS
`else // PIPELINED_BUS_ACCESS
        memops  #(AW,IMPLEMENT_LOCK) domem(i_clk, i_rst, mem_ce, bus_lock,
        memops  #(AW,IMPLEMENT_LOCK) domem(i_clk, i_rst,(mem_ce)&&(set_cond), bus_lock,
                                (opn[0]), opB, opA, opR,
                                (opn[0]), opB, opA, opR,
                                mem_busy,
                                mem_busy,
                                mem_valid, bus_err, mem_wreg, mem_result,
                                mem_valid, bus_err, mem_wreg, mem_result,
                        mem_cyc_gbl, mem_cyc_lcl,
                        mem_cyc_gbl, mem_cyc_lcl,
                                mem_stb_gbl, mem_stb_lcl,
                                mem_stb_gbl, mem_stb_lcl,
Line 1188... Line 1163...
        //      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)&&(~clear_pipeline))||(mem_valid)||(div_valid)||(fpu_valid);
        assign  wr_reg_ce = (~alu_illegal)&&((alu_wr)&&(alu_valid)&&(~clear_pipeline))||(mem_valid)||(div_valid)||(fpu_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 1203... Line 1178...
        // Are we writing to the CC register?
        // Are we writing to the CC register?
        assign  wr_write_cc = (wr_reg_id[3:0] == `CPU_CC_REG);
        assign  wr_write_cc = (wr_reg_id[3:0] == `CPU_CC_REG);
        // Are we writing to the PC?
        // Are we writing to the PC?
        assign  wr_write_pc = (wr_reg_id[3:0] == `CPU_PC_REG);
        assign  wr_write_pc = (wr_reg_id[3:0] == `CPU_PC_REG);
        // What value to write?
        // What value to write?
        assign  wr_reg_vl = (alu_wr)?((dbgv)?dbg_val: alu_result)
        assign  wr_reg_vl = ((mem_valid) ? mem_result
                                :((mem_valid) ? mem_result
                                :((div_valid|fpu_valid))
                                :((div_valid) ? div_result
                                        ? ((div_valid) ? div_result:fpu_result)
                                :fpu_result));
                                :((dbgv) ? dbg_val : alu_result));
        always @(posedge i_clk)
        always @(posedge i_clk)
                if (wr_reg_ce)
                if (wr_reg_ce)
                        regset[wr_reg_id] <= wr_reg_vl;
                        regset[wr_reg_id] <= wr_reg_vl;
 
 
        //
        //
        // 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, udiv_err_flag, ubus_err_flag, trap, ill_err_u,    1'b0, step, 1'b1, sleep, ((wr_flags_ce)&&(alu_gie))?alu_flags:flags };
        assign  w_uflags = { ufpu_err_flag,
        assign  w_iflags = { ifpu_err_flag, idiv_err_flag, ibus_err_flag, trap, ill_err_i,break_en, 1'b0, 1'b0, sleep, ((wr_flags_ce)&&(~alu_gie))?alu_flags:iflags };
                        udiv_err_flag, ubus_err_flag, trap, ill_err_u,
 
                        1'b0, step, 1'b1, sleep,
 
                        ((wr_flags_ce)&&(alu_gie))?alu_flags:flags };
 
        assign  w_iflags = { ifpu_err_flag,
 
                        idiv_err_flag, ibus_err_flag, trap, ill_err_i,
 
                        break_en, 1'b0, 1'b0, sleep,
 
                        ((wr_flags_ce)&&(~alu_gie))?alu_flags:iflags };
 
 
 
 
        // What value to write?
        // What value to write?
        always @(posedge i_clk)
        always @(posedge i_clk)
                // If explicitly writing the register itself
                // If explicitly writing the register itself
Line 1266... Line 1247...
                                &&(~div_busy)&&(~fpu_busy)
                                &&(~div_busy)&&(~fpu_busy)
                                &&(~clear_pipeline)
                                &&(~clear_pipeline)
                        ||((~alu_gie)&&(bus_err))
                        ||((~alu_gie)&&(bus_err))
                        ||((~alu_gie)&&(div_valid)&&(div_error))
                        ||((~alu_gie)&&(div_valid)&&(div_error))
                        ||((~alu_gie)&&(fpu_valid)&&(fpu_error))
                        ||((~alu_gie)&&(fpu_valid)&&(fpu_error))
                        ||((~alu_gie)&&(alu_valid)&&(alu_illegal));
                        ||((~alu_gie)&&(alu_pc_valid)&&(alu_illegal));
`else
`else
        assign  o_break = (((break_en)||(~op_gie))&&(op_break)
        assign  o_break = (((break_en)||(~op_gie))&&(op_break)
                                &&(~alu_valid)&&(~mem_valid)&&(~mem_busy)
                                &&(~alu_valid)&&(~mem_valid)&&(~mem_busy)
                                &&(~clear_pipeline))
                                &&(~clear_pipeline))
                        ||((~alu_gie)&&(bus_err));
                        ||((~alu_gie)&&(bus_err));
Line 1322... Line 1303...
                        //      enable isn't set.
                        //      enable isn't set.
                        ||((master_ce)&&(~mem_rdbusy)&&(~div_busy)&&(~fpu_busy)
                        ||((master_ce)&&(~mem_rdbusy)&&(~div_busy)&&(~fpu_busy)
                                &&(op_break)&&(~break_en))
                                &&(op_break)&&(~break_en))
`ifdef  OPT_ILLEGAL_INSTRUCTION
`ifdef  OPT_ILLEGAL_INSTRUCTION
                        // On an illegal instruction
                        // On an illegal instruction
                        ||((alu_valid)&&(alu_illegal))
                        ||((alu_pc_valid)&&(alu_illegal))
`endif
`endif
 
                        // On division by zero.  If the divide isn't
 
                        // implemented, div_valid and div_error will be short
 
                        // circuited and that logic will be bypassed
                        ||((div_valid)&&(div_error))
                        ||((div_valid)&&(div_error))
 
                        // Same thing on a floating point error.
                        ||((fpu_valid)&&(fpu_error))
                        ||((fpu_valid)&&(fpu_error))
 
                        //      
                        ||(bus_err)
                        ||(bus_err)
                        // If we write to the CC register
                        // If we write to the CC register
                        ||((wr_reg_ce)&&(~wr_reg_vl[`CPU_GIE_BIT])
                        ||((wr_reg_ce)&&(~wr_reg_vl[`CPU_GIE_BIT])
                                &&(wr_reg_id[4])&&(wr_write_cc))
                                &&(wr_reg_id[4])&&(wr_write_cc))
                        );
                        );
Line 1363... Line 1349...
                        ill_err_i <= 1'b0;
                        ill_err_i <= 1'b0;
                // The debug interface can clear this bit
                // The debug interface can clear this bit
                else if ((dbgv)&&(wr_reg_id == {1'b0, `CPU_CC_REG})
                else if ((dbgv)&&(wr_reg_id == {1'b0, `CPU_CC_REG})
                                &&(~wr_reg_vl[`CPU_ILL_BIT]))
                                &&(~wr_reg_vl[`CPU_ILL_BIT]))
                        ill_err_i <= 1'b0;
                        ill_err_i <= 1'b0;
                else if ((alu_valid)&&(alu_illegal)&&(~alu_gie))
                else if ((alu_pc_valid)&&(alu_illegal)&&(~alu_gie))
                        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)
                if (i_rst)
                if (i_rst)
                        ill_err_u <= 1'b0;
                        ill_err_u <= 1'b0;
Line 1378... Line 1364...
                // bit, then clear it
                // bit, then clear it
                else if (((~alu_gie)||(dbgv))
                else if (((~alu_gie)||(dbgv))
                                &&(wr_reg_ce)&&(~wr_reg_vl[`CPU_ILL_BIT])
                                &&(wr_reg_ce)&&(~wr_reg_vl[`CPU_ILL_BIT])
                                &&(wr_reg_id[4])&&(wr_write_cc))
                                &&(wr_reg_id[4])&&(wr_write_cc))
                        ill_err_u <= 1'b0;
                        ill_err_u <= 1'b0;
                else if ((alu_valid)&&(alu_illegal)&&(gie))
                else if ((alu_pc_valid)&&(alu_illegal)&&(alu_gie))
                        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 1612... Line 1598...
        //
        //
        // Produce accounting outputs: Account for any CPU stalls, so we can
        // Produce accounting outputs: Account for any CPU stalls, so we can
        // later evaluate how well we are doing.
        // later evaluate how well we are doing.
        //
        //
        //
        //
        assign  o_op_stall = (master_ce)&&((~opvalid)||(op_stall));
        assign  o_op_stall = (master_ce)&&(op_stall);
        assign  o_pf_stall = (master_ce)&&(~pf_valid);
        assign  o_pf_stall = (master_ce)&&(~pf_valid);
        assign  o_i_count  = (alu_pc_valid)&&(~clear_pipeline);
        assign  o_i_count  = (alu_pc_valid)&&(~clear_pipeline);
 
 
`ifdef  DEBUG_SCOPE
`ifdef  DEBUG_SCOPE
        always @(posedge i_clk)
        always @(posedge i_clk)
                o_debug <= {
                o_debug <= {
 
                        pf_pc[3:0], flags,
 
                        pf_valid, dcdvalid, opvalid, alu_valid, mem_valid,
 
                        op_ce, alu_ce, mem_ce,
 
                        //
 
                        master_ce, opvalid_alu, opvalid_mem,
 
                        //
 
                        alu_stall, mem_busy, op_pipe, mem_pipe_stalled,
 
                        mem_we,
 
                        // ((opvalid_alu)&&(alu_stall))
 
                        // ||((opvalid_mem)&&(~op_pipe)&&(mem_busy))
 
                        // ||((opvalid_mem)&&( op_pipe)&&(mem_pipe_stalled)));
 
                        // opA[23:20], opA[3:0],
 
                        gie, sleep,
 
                        wr_reg_ce, wr_reg_vl[4:0]
                /*
                /*
                        pf_pc[3:0], flags,
                        i_rst, master_ce, (new_pc),
                        pf_valid, dcdvalid, opvalid, alu_valid, mem_valid,
                        ((dcd_early_branch)&&(dcdvalid)),
                        op_ce, alu_ce, mem_ce,
                        pf_valid, pf_illegal,
                        //
                        op_ce, dcd_ce, dcdvalid, dcd_stalled,
                        master_ce, opvalid_alu, opvalid_mem,
                        pf_cyc, pf_stb, pf_we, pf_ack, pf_stall, pf_err,
                        //
                        pf_pc[7:0], pf_addr[7:0]
                        alu_stall, mem_busy, op_pipe, mem_pipe_stalled,
 
                        mem_we,
 
                        // ((opvalid_alu)&&(alu_stall))
 
                        // ||((opvalid_mem)&&(~op_pipe)&&(mem_busy))
 
                        // ||((opvalid_mem)&&( op_pipe)&&(mem_pipe_stalled)));
 
                        // opA[23:20], opA[3:0],
 
                        gie, sleep,
 
                        wr_reg_vl[5:0]
 
                */
                */
                        i_rst, master_ce, (new_pc),
 
                        ((dcd_early_branch)&&(dcdvalid)),
 
                        pf_valid, pf_illegal,
 
                        op_ce, dcd_ce, dcdvalid, dcd_stalled,
 
                        pf_cyc, pf_stb, pf_we, pf_ack, pf_stall, pf_err,
 
                        pf_pc[7:0], pf_addr[7:0]
 
                        };
                        };
`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.