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

Subversion Repositories cpu16

[/] [cpu16/] [trunk/] [cpu16.v] - Diff between revs 2 and 3

Only display areas with differences | Details | Blame | View Log

Rev 2 Rev 3
/*
/*
 * None pipelined, 3-state, 16-bit CPU
 * None pipelined, 3-state, 16-bit CPU
 *
 *
 * Copyright (C) 2019, Yvo Zoer
 * Copyright (C) 2019, Yvo Zoer
 *
 *
 * This program is free software; you can redistribute it and/or
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 * of the License, or (at your option) any later version.
 *
 *
 * This program is distributed in the hope that it will be useful,
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * GNU General Public License for more details.
 *
 *
 * You should have received a copy of the GNU General Public License
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */
 */
 
 
 
// comment this line out to use LE's (warning: size goes up dramatically to around 800LE's)
 
`define USE_RAM_FOR_REGFILE
 
 
 
 
module cpu16 (
module cpu16 (
        clk,
        clk,
        reset_n,
        reset_n,
        clk_en,
        clk_en,
        address,
        address,
        din,
        din,
        dout,
        dout,
        cs_n,
        cs_n,
        oe_n,
        oe_n,
        we_n,
        we_n,
        ub_n,
        ub_n,
        lb_n,
        lb_n,
        irq,            // combined interrupt request from intc
        irq,            // combined interrupt request from intc
        busreq,
        busreq,
        busack
        busack
        );
        );
 
 
        input clk;
        input clk;
        input reset_n;
        input reset_n;
        output [15:0] address;
        output [15:0] address;
        input clk_en;
        input clk_en;
        input [15:0] din;
        input [15:0] din;
        output [15:0] dout;
        output [15:0] dout;
        output cs_n;
        output cs_n;
        output oe_n;
        output oe_n;
        output we_n;
        output we_n;
        output ub_n;
        output ub_n;
        output lb_n;
        output lb_n;
        input irq;
        input irq;
        input busreq;
        input busreq;
        output busack;
        output busack;
 
 
        // alu
        // alu
        parameter OP_SUB                = 5'd0;         // ok
        parameter OP_SUB                = 5'd0;         // ok
        parameter OP_SBC                = 5'd1;         // ok
        parameter OP_SBC                = 5'd1;         // ok
        parameter OP_ADD                = 5'd2;
        parameter OP_ADD                = 5'd2;
        parameter OP_ADC                = 5'd3;
        parameter OP_ADC                = 5'd3;
        parameter OP_CMP                = 5'd4;
        parameter OP_CMP                = 5'd4;
        parameter OP_AND                = 5'd5;         // ok
        parameter OP_AND                = 5'd5;         // ok
        parameter OP_OR                 = 5'd6;         // ok
        parameter OP_OR                 = 5'd6;         // ok
        parameter OP_XOR                = 5'd7;         // ok
        parameter OP_XOR                = 5'd7;         // ok
 
 
        // alu immediate
        // alu immediate
        parameter OP_SUBI               = 5'd8;         // ok
        parameter OP_SUBI               = 5'd8;         // ok
        parameter OP_SBCI               = 5'd9;         // ok
        parameter OP_SBCI               = 5'd9;         // ok
        parameter OP_ADDI               = 5'd10;        // ok
        parameter OP_ADDI               = 5'd10;        // ok
        parameter OP_ADCI               = 5'd11;        // ok
        parameter OP_ADCI               = 5'd11;        // ok
        parameter OP_CMPI               = 5'd12;
        parameter OP_CMPI               = 5'd12;
        parameter OP_ANDI               = 5'd13;        // ok
        parameter OP_ANDI               = 5'd13;        // ok
        parameter OP_ORI                = 5'd14;        // ok
        parameter OP_ORI                = 5'd14;        // ok
        parameter OP_XORI               = 5'd15;        // ok
        parameter OP_XORI               = 5'd15;        // ok
 
 
        // shifter + load
        // shifter + load
        parameter OP_MOV                = 5'd16;
        parameter OP_MOV                = 5'd16;
        parameter OP_SRAV               = 5'd17;
        parameter OP_SRAV               = 5'd17;
        parameter OP_SLLV               = 5'd18;
        parameter OP_SLLV               = 5'd18;
        parameter OP_LD                 = 5'd19;
        parameter OP_LD                 = 5'd19;
 
 
        // shifter immediate + store
        // shifter immediate + store
        parameter OP_LUI                = 5'd20;
        parameter OP_LUI                = 5'd20;
        parameter OP_SRA                = 5'd21;
        parameter OP_SRA                = 5'd21;
        parameter OP_SLL                = 5'd22;
        parameter OP_SLL                = 5'd22;
        parameter OP_ST                 = 5'd23;
        parameter OP_ST                 = 5'd23;
 
 
        // jump
        // jump
        parameter OP_J                  = 5'd24;
        parameter OP_J                  = 5'd24;
        parameter OP_JAL                = 5'd25;
        parameter OP_JAL                = 5'd25;
        parameter OP_JR                 = 5'd26;
        parameter OP_JR                 = 5'd26;
        parameter OP_JALR               = 5'd27;
        parameter OP_JALR               = 5'd27;
 
 
        // conditional branch
        // conditional branch
        parameter OP_BXX                = 5'd28;
        parameter OP_BXX                = 5'd28;
        parameter OP_MSR                = 5'd29;
        parameter OP_MSR                = 5'd29;
        parameter OP_RFE                = 5'd30;
        parameter OP_RFE                = 5'd30;
        parameter OP_SWI                = 5'd31;
        parameter OP_SWI                = 5'd31;
 
 
        // states
        // states
        parameter STATE_FETCH   = 4'h0;
        parameter STATE_FETCH   = 4'h0;
        parameter STATE_DECODE  = 4'h1;
        parameter STATE_DECODE  = 4'h1;
        parameter STATE_ALU             = 4'h2;
        parameter STATE_ALU             = 4'h2;
        parameter STATE_SHIFT   = 4'h3;
        parameter STATE_SHIFT   = 4'h3;
        parameter STATE_LOAD    = 4'h4;
        parameter STATE_LOAD    = 4'h4;
        parameter STATE_STORE   = 4'h5;
        parameter STATE_STORE   = 4'h5;
        parameter STATE_J               = 4'h6;
        parameter STATE_J               = 4'h6;
        parameter STATE_JAL             = 4'h7;
        parameter STATE_JAL             = 4'h7;
        parameter STATE_BRANCH  = 4'h8;
        parameter STATE_BRANCH  = 4'h8;
        parameter STATE_MOVSR   = 4'h9;
        parameter STATE_MOVSR   = 4'h9;
        parameter STATE_RFE             = 4'ha;
        parameter STATE_RFE             = 4'ha;
        parameter STATE_SWI             = 4'hb;
        parameter STATE_SWI             = 4'hb;
        parameter STATE_INTREQ  = 4'hc;
        parameter STATE_INTREQ  = 4'hc;
        parameter STATE_BUSREQ  = 4'hd;
        parameter STATE_BUSREQ  = 4'hd;
 
 
        // instruction register wires
        // instruction register wires
        wire [4:0] ir_opcode = ir[15:11];
        wire [4:0] ir_opcode = ir[15:11];
        wire [2:0] ir_dst = ir[10:8];
        wire [2:0] ir_dst = ir[10:8];
        wire [2:0] ir_src = ir[7:5];
        wire [2:0] ir_src = ir[7:5];
        wire ir_size = ir[4];   // byte/word flag
        wire ir_size = ir[4];   // byte/word flag
        wire [3:0] ir_imm4 = ir[3:0];     // load/store offset
        wire [3:0] ir_imm4 = ir[3:0];     // load/store offset
        wire [7:0] ir_imm8 = ir[7:0];     // immediate value / relative conditional branch
        wire [7:0] ir_imm8 = ir[7:0];     // immediate value / relative conditional branch
        wire [10:0] ir_imm11 = ir[10:0];  // unconditional branch 
        wire [10:0] ir_imm11 = ir[10:0];  // unconditional branch 
 
 
        // busack valid once we're in the busreq state
        // busack valid once we're in the busreq state
        reg busack;
        reg busack;
        always @(*)
        always @(*)
                if ( state == STATE_BUSREQ )
                if ( state == STATE_BUSREQ )
                        busack = 1'b1;
                        busack = 1'b1;
                else
                else
                        busack = 1'b0;
                        busack = 1'b0;
 
 
// chip-select
// chip-select
        reg cs_n;
        reg cs_n;
        always @(*)
        always @(*)
                case (state)
                case (state)
                        STATE_FETCH,
                        STATE_FETCH,
                        STATE_LOAD,
                        STATE_LOAD,
                        STATE_STORE : cs_n = 1'b0;
                        STATE_STORE : cs_n = 1'b0;
                        default : cs_n = 1'b1;
                        default : cs_n = 1'b1;
                endcase
                endcase
 
 
        // output enable
        // output enable
        reg oe_n;
        reg oe_n;
        always @(*)
        always @(*)
                case (state)
                case (state)
                        STATE_FETCH,
                        STATE_FETCH,
                        STATE_LOAD : oe_n = 1'b0;
                        STATE_LOAD : oe_n = 1'b0;
                        default : oe_n = 1'b1;
                        default : oe_n = 1'b1;
                endcase
                endcase
        // memory write signal
        // memory write signal
        reg we_n;
        reg we_n;
        always @(posedge clk)
        always @(posedge clk)
                if ( state == STATE_STORE )
                if ( state == STATE_STORE )
                        we_n <= clk_en;
                        we_n <= clk_en;
                else
                else
                        we_n <= 1'b1;
                        we_n <= 1'b1;
 
 
        // upper / lower byte write/read enable
        // upper / lower byte write/read enable
        // NOTE: could integrate dout here as well..
        // NOTE: could integrate dout here as well..
        reg ub_n;
        reg ub_n;
        reg lb_n;
        reg lb_n;
        always @(*)
        always @(*)
                if ( state == STATE_STORE )
                if ( state == STATE_STORE )
                        begin
                        begin
                                if ( ir_size )
                                if ( ir_size )
                                        begin   // word
                                        begin   // word
                                                ub_n = 1'b0;
                                                ub_n = 1'b0;
                                                lb_n = 1'b0;
                                                lb_n = 1'b0;
                                        end
                                        end
                                else
                                else
                                        begin   // byte
                                        begin   // byte
                                                if ( address[0] )
                                                if ( address[0] )
                                                        begin
                                                        begin
                                                                ub_n = 1'b1;
                                                                ub_n = 1'b1;
                                                                lb_n = 1'b0;
                                                                lb_n = 1'b0;
                                                        end
                                                        end
                                                else
                                                else
                                                        begin
                                                        begin
                                                                ub_n = 1'b0;
                                                                ub_n = 1'b0;
                                                                lb_n = 1'b1;
                                                                lb_n = 1'b1;
                                                        end
                                                        end
                                        end
                                        end
                        end
                        end
                else
                else
                        begin   // word access for everything else
                        begin   // word access for everything else
                                ub_n = 1'b0;
                                ub_n = 1'b0;
                                lb_n = 1'b0;
                                lb_n = 1'b0;
                        end
                        end
 
 
        // data output logic
        // data output logic
        reg [15:0] dout;
        reg [15:0] dout;
        always @(*)
        always @(*)
                if ( ir_size )
                if ( ir_size )
                        dout = qa;      // word
                        dout = qa;      // word
                else
                else
                        begin
                        begin
                                if ( address[0] )
                                if ( address[0] )
                                        dout = { 8'h00, qa[7:0] };
                                        dout = { 8'h00, qa[7:0] };
                                else
                                else
                                        dout = { qa[7:0], 8'h00 };
                                        dout = { qa[7:0], 8'h00 };
                        end
                        end
 
 
        // address mux 
        // address mux 
        reg [15:0] address;
        reg [15:0] address;
        always @(*)
        always @(*)
                case (state)
                case (state)
                        STATE_LOAD,
                        STATE_LOAD,
                        STATE_STORE : address = qb + ir_imm4;
                        STATE_STORE : address = qb + ir_imm4;
                        default : address = pc; // { pc[15:1], 1'b0 };
                        default : address = pc; // { pc[15:1], 1'b0 };
                endcase
                endcase
 
 
        // main state machine
        // main state machine
        reg [3:0] state, next_state;
        reg [3:0] state, next_state;
        always @(*)
        always @(*)
                case (state)
                case (state)
                        STATE_FETCH : next_state = STATE_DECODE;
                        STATE_FETCH : next_state = STATE_DECODE;
                        STATE_DECODE : begin
                        STATE_DECODE : begin
                                casex (ir_opcode)
                                casex (ir_opcode)
                                        5'b0xxxx : next_state = STATE_ALU;              // sub/sbc/add/adc/and/or/xor/cmp
                                        5'b0xxxx : next_state = STATE_ALU;              // sub/sbc/add/adc/and/or/xor/cmp
                                        5'b10x0x,
                                        5'b10x0x,
                                        5'b10x10 : next_state = STATE_SHIFT;
                                        5'b10x10 : next_state = STATE_SHIFT;
                                        5'b10011 : next_state = STATE_LOAD;
                                        5'b10011 : next_state = STATE_LOAD;
                                        5'b10111 : next_state = STATE_STORE;
                                        5'b10111 : next_state = STATE_STORE;
                                        5'b110x0 : next_state = STATE_J;        // 24/26
                                        5'b110x0 : next_state = STATE_J;        // 24/26
                                        5'b110x1 : next_state = STATE_JAL;      // 25/27
                                        5'b110x1 : next_state = STATE_JAL;      // 25/27
                                        5'b11100 : next_state = STATE_BRANCH;
                                        5'b11100 : next_state = STATE_BRANCH;
                                        5'b11101 : next_state = STATE_MOVSR;
                                        5'b11101 : next_state = STATE_MOVSR;
                                        5'b11110 : next_state = STATE_RFE;
                                        5'b11110 : next_state = STATE_RFE;
                                        5'b11111 : next_state = STATE_SWI;
                                        5'b11111 : next_state = STATE_SWI;
                                        default : next_state = STATE_FETCH;
                                        default : next_state = STATE_FETCH;
                                endcase
                                endcase
                                end
                                end
                        STATE_INTREQ : next_state = STATE_FETCH;
                        STATE_INTREQ : next_state = STATE_FETCH;
                        STATE_BUSREQ : begin
                        STATE_BUSREQ : begin
                                if ( busreq )
                                if ( busreq )
                                        next_state = STATE_BUSREQ;
                                        next_state = STATE_BUSREQ;
                                else
                                else
                                        next_state = STATE_FETCH;       // will miss interrupt when coming out of busreq (STATE_NOP?)
                                        next_state = STATE_FETCH;       // will miss interrupt when coming out of busreq (STATE_NOP?)
                                end
                                end
                        default : begin
                        default : begin
                                if ( busreq )
                                if ( busreq )
                                        next_state = STATE_BUSREQ;
                                        next_state = STATE_BUSREQ;
                                else if ( irq & i )     // only fires when interrupt enable is set (i = 1)
                                else if ( irq & i )     // only fires when interrupt enable is set (i = 1)
                                        next_state = STATE_INTREQ;
                                        next_state = STATE_INTREQ;
                                else
                                else
                                        next_state = STATE_FETCH;
                                        next_state = STATE_FETCH;
                                end
                                end
                endcase
                endcase
 
 
        // instruction register
        // instruction register
        reg [15:0] ir, next_ir;
        reg [15:0] ir, next_ir;
        always @(*)
        always @(*)
                if ( state == STATE_FETCH )
                if ( state == STATE_FETCH )
                        next_ir = din;
                        next_ir = din;
                else
                else
                        next_ir = ir;
                        next_ir = ir;
 
 
        // exception pc- and status register
        // exception pc- and status register
        reg [15:0] epc, next_epc;
        reg [15:0] epc, next_epc;
        reg [4:0] esr, next_esr;
        reg [4:0] esr, next_esr;
        always @(*)
        always @(*)
                case (state)
                case (state)
                        STATE_INTREQ : begin
                        STATE_INTREQ : begin
                                next_epc = pc;
                                next_epc = pc;
                                next_esr = { i,n,v,z,c };
                                next_esr = { i,n,v,z,c };
                                end
                                end
                        default : begin
                        default : begin
                                next_epc = epc;
                                next_epc = epc;
                                next_esr = esr;
                                next_esr = esr;
                                end
                                end
                endcase
                endcase
 
 
        // source data for program counter ( register / immediate )
        // source data for program counter ( register / immediate )
        reg [15:0] pc_data;
        reg [15:0] pc_data;
        always @(*)
        always @(*)
                if ( ir_opcode[1] )     // immediate for PC
                if ( ir_opcode[1] )     // immediate for PC
                        pc_data = qb;   //{ qb[15:1], 1'b0 };   // TEST: jr/jalr
                        pc_data = qb;   //{ qb[15:1], 1'b0 };   // TEST: jr/jalr
                else
                else
                        pc_data = pc + { { 4 { ir_imm11[10] } }, ir_imm11[10:0], 1'b0 }; // TEST: j/jal doubled for jumps
                        pc_data = pc + { { 4 { ir_imm11[10] } }, ir_imm11[10:0], 1'b0 }; // TEST: j/jal doubled for jumps
 
 
        // condition check
        // condition check
        reg condition_true;
        reg condition_true;
        always @(*)
        always @(*)
                case (ir_dst)
                case (ir_dst)
                        3'd0 : condition_true = z;
                        3'd0 : condition_true = z;
                        3'd1 : condition_true = ~z;
                        3'd1 : condition_true = ~z;
                        3'd2 : condition_true = ~n;
                        3'd2 : condition_true = ~n;
                        3'd3 : condition_true = n;
                        3'd3 : condition_true = n;
                        3'd4 : condition_true = ~c;
                        3'd4 : condition_true = ~c;
                        3'd5 : condition_true = c;
                        3'd5 : condition_true = c;
                        3'd6 : condition_true = ~v;
                        3'd6 : condition_true = ~v;
                        3'd7 : condition_true = v;
                        3'd7 : condition_true = v;
                endcase
                endcase
 
 
        // program counter
        // program counter
        reg [15:0] pc, next_pc;
        reg [15:0] pc, next_pc;
        always @(*)
        always @(*)
                case (state)
                case (state)
                        STATE_FETCH : next_pc = pc + 16'd2;
                        STATE_FETCH : next_pc = pc + 16'd2;
                        STATE_SWI : next_pc = { ir_imm8, 1'b0 };
                        STATE_SWI : next_pc = { ir_imm8, 1'b0 };
                        STATE_J,
                        STATE_J,
                        STATE_JAL : next_pc = pc_data;
                        STATE_JAL : next_pc = pc_data;
                        STATE_BRANCH : begin
                        STATE_BRANCH : begin
                                if ( condition_true )
                                if ( condition_true )
                                        next_pc = pc + { {  7 { ir_imm8[7] } }, ir_imm8[7:0], 1'b0 };
                                        next_pc = pc + { {  7 { ir_imm8[7] } }, ir_imm8[7:0], 1'b0 };
                                else
                                else
                                        next_pc = pc;
                                        next_pc = pc;
                                end
                                end
                        STATE_INTREQ : next_pc = 16'h0002;      // interrupt vector appears at 0x0002
                        STATE_INTREQ : next_pc = 16'h0002;      // interrupt vector appears at 0x0002
                        STATE_RFE : next_pc = epc;
                        STATE_RFE : next_pc = epc;
                        default : next_pc = pc;
                        default : next_pc = pc;
                endcase
                endcase
 
 
        // alu data mux
        // alu data mux
        reg [15:0] alu_data;
        reg [15:0] alu_data;
        always @(*)
        always @(*)
                if (ir_opcode[3])       // immediate
                if (ir_opcode[3])       // immediate
                        alu_data = { 8'h00, ir_imm8 };
                        alu_data = { 8'h00, ir_imm8 };
                else
                else
                        alu_data = qb;  // register
                        alu_data = qb;  // register
 
 
        // alu
        // alu
        wire [15:0] alu_result;
        wire [15:0] alu_result;
        wire alu_n;
        wire alu_n;
        wire alu_v;
        wire alu_v;
        wire alu_z;
        wire alu_z;
        wire alu_c;
        wire alu_c;
        alu i_alu (
        alu i_alu (
                .a(qa),
                .a(qa),
                .b(alu_data),
                .b(alu_data),
                .c_in(c),
                .c_in(c),
                .func(ir_opcode[2:0]),
                .func(ir_opcode[2:0]),
                .result(alu_result),
                .result(alu_result),
                .n(alu_n),
                .n(alu_n),
                .v(alu_v),
                .v(alu_v),
                .z(alu_z),
                .z(alu_z),
                .c(alu_c)
                .c(alu_c)
                );
                );
 
 
        // shifter data mux
        // shifter data mux
        reg [15:0] shifter_data;
        reg [15:0] shifter_data;
        always @(*)
        always @(*)
                if ( ir_opcode[2] )     // immediate
                if ( ir_opcode[2] )     // immediate
                        shifter_data = { ir_imm8, 8'h00 };      // lui from instruction word
                        shifter_data = { ir_imm8, 8'h00 };      // lui from instruction word
                else
                else
                        shifter_data = qb;      // mov
                        shifter_data = qb;      // mov
 
 
        // shifter distance -- roll into b argument inside shifter?
        // shifter distance -- roll into b argument inside shifter?
        reg [3:0] shift_distance;
        reg [3:0] shift_distance;
        always @(*)
        always @(*)
                if ( ir_opcode[2] )
                if ( ir_opcode[2] )
                        shift_distance = ir_imm4;
                        shift_distance = ir_imm4;
                else
                else
                        shift_distance = qb[3:0];
                        shift_distance = qb[3:0];
 
 
        // shifter
        // shifter
        wire [15:0] shifter_result;
        wire [15:0] shifter_result;
        wire shift_n;
        wire shift_n;
        wire shift_z;
        wire shift_z;
        wire shift_c;
        wire shift_c;
        wire shift_v;
        wire shift_v;
        shifter i_shifter (
        shifter i_shifter (
                .a(qa),
                .a(qa),
                .b(shifter_data),
                .b(shifter_data),
                .n_in(n),
                .n_in(n),
                .v_in(v),
                .v_in(v),
                .z_in(z),
                .z_in(z),
                .c_in(c),
                .c_in(c),
                .distance(shift_distance),
                .distance(shift_distance),
                .func(ir_opcode[1:0]),
                .func(ir_opcode[1:0]),
                .result(shifter_result),
                .result(shifter_result),
                .n(shift_n),
                .n(shift_n),
                .v(shift_v),
                .v(shift_v),
                .z(shift_z),
                .z(shift_z),
                .c(shift_c)
                .c(shift_c)
                );
                );
 
 
        // memory data mux for lw/lb
        // memory data mux for lw/lb
        reg [15:0] mem_data;
        reg [15:0] mem_data;
        always @(*)
        always @(*)
                if ( ir_size )
                if ( ir_size )
                        mem_data = din;
                        mem_data = din;
                else
                else
                        begin
                        begin
                                if ( address[0] )
                                if ( address[0] )
                                        mem_data = { 8'h00, din[7:0] };
                                        mem_data = { 8'h00, din[7:0] };
                                else
                                else
                                        mem_data = { 8'h00, din[15:8] };
                                        mem_data = { 8'h00, din[15:8] };
                        end
                        end
 
 
        // register data
        // register data
        reg [15:0] reg_data;
        reg [15:0] reg_data;
        always @(*)
        always @(*)
                case (state)
                case (state)
                        STATE_ALU : reg_data = alu_result;
                        STATE_ALU : reg_data = alu_result;
                        STATE_SHIFT : reg_data = shifter_result;
                        STATE_SHIFT : reg_data = shifter_result;
                        STATE_JAL,
                        STATE_JAL,
                        STATE_SWI : reg_data = pc;
                        STATE_SWI : reg_data = pc;
                        default : reg_data = mem_data;
                        default : reg_data = mem_data;
                endcase
                endcase
 
 
        // register writeback
        // register writeback
        reg reg_write;
        reg reg_write;
        always @(*)
        always @(*)
                case (state)
                case (state)
                        STATE_ALU,
                        STATE_ALU,
                        STATE_SHIFT,
                        STATE_SHIFT,
                        STATE_LOAD,
                        STATE_LOAD,
                        STATE_JAL,
                        STATE_JAL,
                        STATE_SWI : reg_write = 1'b1;
                        STATE_SWI : reg_write = 1'b1;
                        default : reg_write = 1'b0;
                        default : reg_write = 1'b0;
                endcase
                endcase
 
 
        // override dst address for JAL to save 3 bits
        // override dst address for JAL to save 3 bits
        reg [2:0] ra_dst;
        reg [2:0] ra_dst;
        always @(*)
        always @(*)
                if ( state == STATE_JAL )
                if ( state == STATE_JAL )
                        ra_dst = 3'd6;  // hard linked register
                        ra_dst = 3'd6;  // hard linked register
                else
                else
                        ra_dst = ir_dst;
                        ra_dst = ir_dst;
 
 
        // register file        
        // register file        
 
        `ifdef USE_RAM_FOR_REGFILE
        wire [15:0] qa, qb;
        wire [15:0] qa, qb;
        regfile8x16 i_regfile (
                regfile8x16 i_regfile (
                .clock(clk),
                        .clock(clk),
                .data(reg_data),
                        .data(reg_data),
                .rdaddress_a(ir_dst),
                        .rdaddress_a(ir_dst),
                .rdaddress_b(ir_src),
                        .rdaddress_b(ir_src),
                .wraddress(ra_dst),
                        .wraddress(ra_dst),
                .wren(reg_write&clk_en),
                        .wren(reg_write&clk_en),
                .qa(qa),
                        .qa(qa),
                .qb(qb)
                        .qb(qb)
                );
                );
 
        `else
 
                reg [15:0] regs[7:0];
 
                always @(posedge clk)
 
                        if (reg_write&clk_en)
 
                                regs[ir_dst] <= reg_data;
 
                wire [15:0] qa = regs[ir_dst];
 
                wire [15:0] qb = regs[ir_src];
 
        `endif
 
 
        // flags
        // flags
        reg i, next_i;
        reg i, next_i;
        reg n, next_n;
        reg n, next_n;
        reg v, next_v;
        reg v, next_v;
        reg z, next_z;
        reg z, next_z;
        reg c, next_c;
        reg c, next_c;
        always @(*)
        always @(*)
                case (state)
                case (state)
                        STATE_ALU : begin
                        STATE_ALU : begin
                                next_i = i;
                                next_i = i;
                                next_n = alu_n;
                                next_n = alu_n;
                                next_v = alu_v;
                                next_v = alu_v;
                                next_z = alu_z;
                                next_z = alu_z;
                                next_c = alu_c;
                                next_c = alu_c;
                                end
                                end
                        STATE_SHIFT : begin
                        STATE_SHIFT : begin
                                next_i = i;
                                next_i = i;
                                next_n = shift_n;
                                next_n = shift_n;
                                next_v = shift_v;
                                next_v = shift_v;
                                next_z = shift_z;
                                next_z = shift_z;
                                next_c = shift_c;
                                next_c = shift_c;
                                end
                                end
                        STATE_MOVSR : begin
                        STATE_MOVSR : begin
                                next_i = (i & ~ir_imm8[4]) | ( ir_imm8[7] & ir_imm8[4]);
                                next_i = (i & ~ir_imm8[4]) | ( ir_imm8[7] & ir_imm8[4]);
                                next_n = (n & ~ir_imm8[3]) | ( ir_imm8[7] & ir_imm8[3]);
                                next_n = (n & ~ir_imm8[3]) | ( ir_imm8[7] & ir_imm8[3]);
                                next_v = (v & ~ir_imm8[2]) | ( ir_imm8[7] & ir_imm8[2]);
                                next_v = (v & ~ir_imm8[2]) | ( ir_imm8[7] & ir_imm8[2]);
                                next_z = (z & ~ir_imm8[1]) | ( ir_imm8[7] & ir_imm8[1]);
                                next_z = (z & ~ir_imm8[1]) | ( ir_imm8[7] & ir_imm8[1]);
                                next_c = (c & ~ir_imm8[0]) | ( ir_imm8[7] & ir_imm8[0]);
                                next_c = (c & ~ir_imm8[0]) | ( ir_imm8[7] & ir_imm8[0]);
                                end
                                end
                        STATE_INTREQ : begin
                        STATE_INTREQ : begin
                                next_i = 1'b0;  // disable interrupts
                                next_i = 1'b0;  // disable interrupts
                                next_n = n;
                                next_n = n;
                                next_v = v;
                                next_v = v;
                                next_z = z;
                                next_z = z;
                                next_c = c;
                                next_c = c;
                                end
                                end
                        STATE_RFE : begin
                        STATE_RFE : begin
                                next_i = esr[4];
                                next_i = esr[4];
                                next_n = esr[3];
                                next_n = esr[3];
                                next_v = esr[2];
                                next_v = esr[2];
                                next_z = esr[1];
                                next_z = esr[1];
                                next_c = esr[0];
                                next_c = esr[0];
                                end
                                end
                        default : begin
                        default : begin
                                next_i = i;
                                next_i = i;
                                next_n = n;
                                next_n = n;
                                next_v = v;
                                next_v = v;
                                next_z = z;
                                next_z = z;
                                next_c = c;
                                next_c = c;
                                end
                                end
                endcase
                endcase
 
 
        // synchronous writeback
        // synchronous writeback
        always @(posedge clk or negedge reset_n)
        always @(posedge clk or negedge reset_n)
                if (!reset_n)
                if (!reset_n)
                        begin
                        begin
                                state <= STATE_FETCH;
                                state <= STATE_FETCH;
                                ir <= 16'd0;
                                ir <= 16'd0;
                                pc <= 16'd0;
                                pc <= 16'd0;
                                i <= 1'b1;      // TEST: enable interrupts
                                i <= 1'b1;      // TEST: enable interrupts
                                n <= 1'b0;
                                n <= 1'b0;
                                v <= 1'b0;
                                v <= 1'b0;
                                z <= 1'b0;
                                z <= 1'b0;
                                c <= 1'b0;
                                c <= 1'b0;
                                epc <= 16'd0;
                                epc <= 16'd0;
                                esr <= 5'd0;
                                esr <= 5'd0;
                        end
                        end
                else if ( clk_en )
                else if ( clk_en )
                        begin
                        begin
                                state <= next_state;
                                state <= next_state;
                                ir <= next_ir;
                                ir <= next_ir;
                                pc <= next_pc;
                                pc <= next_pc;
                                i <= next_i;
                                i <= next_i;
                                n <= next_n;
                                n <= next_n;
                                v <= next_v;
                                v <= next_v;
                                z <= next_z;
                                z <= next_z;
                                c <= next_c;
                                c <= next_c;
                                epc <= next_epc;
                                epc <= next_epc;
                                esr <= next_esr;
                                esr <= next_esr;
                        end
                        end
endmodule
endmodule
 
 

powered by: WebSVN 2.1.0

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