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

Subversion Repositories cpu16

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /cpu16/trunk
    from Rev 1 to Rev 2
    Reverse comparison

Rev 1 → Rev 2

/alu.v
0,0 → 1,68
module alu (
a,
b,
c_in,
func,
result,
n,
v,
z,
c
);
input [15:0] a,b;
input c_in;
input [2:0] func;
output [15:0] result;
output n,v,z,c;
reg [15:0] addsub_result;
reg addsub_c;
reg addsub_v;
always @(*)
if ( func[1])
{ addsub_c, addsub_result } = a + b + (c_in&func[0]);
else
{ addsub_c, addsub_result } = a - b - (c_in&func[0]);
 
// overflow calculation
always @(*)
addsub_v = a[15] ^ b[15] ^ addsub_c ^ addsub_result[15];
reg [15:0] logic_result;
always @(*)
case (func[1:0])
2'd0 : logic_result = a; // maps to subtract
2'd1 : logic_result = a&b;
2'd2 : logic_result = a|b;
2'd3 : logic_result = a^b;
endcase
reg [15:0] result;
always @(*)
if ( func[2])
result = logic_result;
else
result = addsub_result;
 
reg n,v,z,c;
always @(*)
casex (func)
3'b0xx, // sub/sbc/add/adc
3'b100 : begin // cmp
n = addsub_result[15];
v = addsub_v;
z = ~|addsub_result;
c = addsub_c;
end
default : begin
n = logic_result[15];
v = 1'b0;
z = ~|logic_result;
c = 1'b0;
end
endcase
 
endmodule
 
alu.v Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: cpu.v =================================================================== --- cpu.v (nonexistent) +++ cpu.v (revision 2) @@ -0,0 +1,512 @@ +/* + * None pipelined, 3-state, 16-bit CPU + * + * Copyright (C) 2019, Yvo Zoer + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +module cpu16 ( + clk, + reset_n, + clk_en, + address, + din, + dout, + cs_n, + oe_n, + we_n, + ub_n, + lb_n, + irq, // combined interrupt request from intc + busreq, + busack + ); + + input clk; + input reset_n; + output [15:0] address; + input clk_en; + input [15:0] din; + output [15:0] dout; + output cs_n; + output oe_n; + output we_n; + output ub_n; + output lb_n; + input irq; + input busreq; + output busack; + + // alu + parameter OP_SUB = 5'd0; // ok + parameter OP_SBC = 5'd1; // ok + parameter OP_ADD = 5'd2; + parameter OP_ADC = 5'd3; + parameter OP_CMP = 5'd4; + parameter OP_AND = 5'd5; // ok + parameter OP_OR = 5'd6; // ok + parameter OP_XOR = 5'd7; // ok + + // alu immediate + parameter OP_SUBI = 5'd8; // ok + parameter OP_SBCI = 5'd9; // ok + parameter OP_ADDI = 5'd10; // ok + parameter OP_ADCI = 5'd11; // ok + parameter OP_CMPI = 5'd12; + parameter OP_ANDI = 5'd13; // ok + parameter OP_ORI = 5'd14; // ok + parameter OP_XORI = 5'd15; // ok + + // shifter + load + parameter OP_MOV = 5'd16; + parameter OP_SRAV = 5'd17; + parameter OP_SLLV = 5'd18; + parameter OP_LD = 5'd19; + + // shifter immediate + store + parameter OP_LUI = 5'd20; + parameter OP_SRA = 5'd21; + parameter OP_SLL = 5'd22; + parameter OP_ST = 5'd23; + + // jump + parameter OP_J = 5'd24; + parameter OP_JAL = 5'd25; + parameter OP_JR = 5'd26; + parameter OP_JALR = 5'd27; + + // conditional branch + parameter OP_BXX = 5'd28; + parameter OP_MSR = 5'd29; + parameter OP_RFE = 5'd30; + parameter OP_SWI = 5'd31; + + // states + parameter STATE_FETCH = 4'h0; + parameter STATE_DECODE = 4'h1; + parameter STATE_ALU = 4'h2; + parameter STATE_SHIFT = 4'h3; + parameter STATE_LOAD = 4'h4; + parameter STATE_STORE = 4'h5; + parameter STATE_J = 4'h6; + parameter STATE_JAL = 4'h7; + parameter STATE_BRANCH = 4'h8; + parameter STATE_MOVSR = 4'h9; + parameter STATE_RFE = 4'ha; + parameter STATE_SWI = 4'hb; + parameter STATE_INTREQ = 4'hc; + parameter STATE_BUSREQ = 4'hd; + + // instruction register wires + wire [4:0] ir_opcode = ir[15:11]; + wire [2:0] ir_dst = ir[10:8]; + wire [2:0] ir_src = ir[7:5]; + wire ir_size = ir[4]; // byte/word flag + 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 [10:0] ir_imm11 = ir[10:0]; // unconditional branch + + // busack valid once we're in the busreq state + reg busack; + always @(*) + if ( state == STATE_BUSREQ ) + busack = 1'b1; + else + busack = 1'b0; + +// chip-select + reg cs_n; + always @(*) + case (state) + STATE_FETCH, + STATE_LOAD, + STATE_STORE : cs_n = 1'b0; + default : cs_n = 1'b1; + endcase + + // output enable + reg oe_n; + always @(*) + case (state) + STATE_FETCH, + STATE_LOAD : oe_n = 1'b0; + default : oe_n = 1'b1; + endcase + // memory write signal + reg we_n; + always @(posedge clk) + if ( state == STATE_STORE ) + we_n <= clk_en; + else + we_n <= 1'b1; + + // upper / lower byte write/read enable + // NOTE: could integrate dout here as well.. + reg ub_n; + reg lb_n; + always @(*) + if ( state == STATE_STORE ) + begin + if ( ir_size ) + begin // word + ub_n = 1'b0; + lb_n = 1'b0; + end + else + begin // byte + if ( address[0] ) + begin + ub_n = 1'b1; + lb_n = 1'b0; + end + else + begin + ub_n = 1'b0; + lb_n = 1'b1; + end + end + end + else + begin // word access for everything else + ub_n = 1'b0; + lb_n = 1'b0; + end + + // data output logic + reg [15:0] dout; + always @(*) + if ( ir_size ) + dout = qa; // word + else + begin + if ( address[0] ) + dout = { 8'h00, qa[7:0] }; + else + dout = { qa[7:0], 8'h00 }; + end + + // address mux + reg [15:0] address; + always @(*) + case (state) + STATE_LOAD, + STATE_STORE : address = qb + ir_imm4; + default : address = pc; // { pc[15:1], 1'b0 }; + endcase + + // main state machine + reg [3:0] state, next_state; + always @(*) + case (state) + STATE_FETCH : next_state = STATE_DECODE; + STATE_DECODE : begin + casex (ir_opcode) + 5'b0xxxx : next_state = STATE_ALU; // sub/sbc/add/adc/and/or/xor/cmp + 5'b10x0x, + 5'b10x10 : next_state = STATE_SHIFT; + 5'b10011 : next_state = STATE_LOAD; + 5'b10111 : next_state = STATE_STORE; + 5'b110x0 : next_state = STATE_J; // 24/26 + 5'b110x1 : next_state = STATE_JAL; // 25/27 + 5'b11100 : next_state = STATE_BRANCH; + 5'b11101 : next_state = STATE_MOVSR; + 5'b11110 : next_state = STATE_RFE; + 5'b11111 : next_state = STATE_SWI; + default : next_state = STATE_FETCH; + endcase + end + STATE_INTREQ : next_state = STATE_FETCH; + STATE_BUSREQ : begin + if ( busreq ) + next_state = STATE_BUSREQ; + else + next_state = STATE_FETCH; // will miss interrupt when coming out of busreq (STATE_NOP?) + end + default : begin + if ( busreq ) + next_state = STATE_BUSREQ; + else if ( irq & i ) // only fires when interrupt enable is set (i = 1) + next_state = STATE_INTREQ; + else + next_state = STATE_FETCH; + end + endcase + + // instruction register + reg [15:0] ir, next_ir; + always @(*) + if ( state == STATE_FETCH ) + next_ir = din; + else + next_ir = ir; + + // exception pc- and status register + reg [15:0] epc, next_epc; + reg [4:0] esr, next_esr; + always @(*) + case (state) + STATE_INTREQ : begin + next_epc = pc; + next_esr = { i,n,v,z,c }; + end + default : begin + next_epc = epc; + next_esr = esr; + end + endcase + + // source data for program counter ( register / immediate ) + reg [15:0] pc_data; + always @(*) + if ( ir_opcode[1] ) // immediate for PC + pc_data = qb; //{ qb[15:1], 1'b0 }; // TEST: jr/jalr + else + pc_data = pc + { { 4 { ir_imm11[10] } }, ir_imm11[10:0], 1'b0 }; // TEST: j/jal doubled for jumps + + // condition check + reg condition_true; + always @(*) + case (ir_dst) + 3'd0 : condition_true = z; + 3'd1 : condition_true = ~z; + 3'd2 : condition_true = ~n; + 3'd3 : condition_true = n; + 3'd4 : condition_true = ~c; + 3'd5 : condition_true = c; + 3'd6 : condition_true = ~v; + 3'd7 : condition_true = v; + endcase + + // program counter + reg [15:0] pc, next_pc; + always @(*) + case (state) + STATE_FETCH : next_pc = pc + 16'd2; + STATE_SWI : next_pc = { ir_imm8, 1'b0 }; + STATE_J, + STATE_JAL : next_pc = pc_data; + STATE_BRANCH : begin + if ( condition_true ) + next_pc = pc + { { 7 { ir_imm8[7] } }, ir_imm8[7:0], 1'b0 }; + else + next_pc = pc; + end + STATE_INTREQ : next_pc = 16'h0002; // interrupt vector appears at 0x0002 + STATE_RFE : next_pc = epc; + default : next_pc = pc; + endcase + + // alu data mux + reg [15:0] alu_data; + always @(*) + if (ir_opcode[3]) // immediate + alu_data = { 8'h00, ir_imm8 }; + else + alu_data = qb; // register + + // alu + wire [15:0] alu_result; + wire alu_n; + wire alu_v; + wire alu_z; + wire alu_c; + alu i_alu ( + .a(qa), + .b(alu_data), + .c_in(c), + .func(ir_opcode[2:0]), + .result(alu_result), + .n(alu_n), + .v(alu_v), + .z(alu_z), + .c(alu_c) + ); + + // shifter data mux + reg [15:0] shifter_data; + always @(*) + if ( ir_opcode[2] ) // immediate + shifter_data = { ir_imm8, 8'h00 }; // lui from instruction word + else + shifter_data = qb; // mov + + // shifter distance -- roll into b argument inside shifter? + reg [3:0] shift_distance; + always @(*) + if ( ir_opcode[2] ) + shift_distance = ir_imm4; + else + shift_distance = qb[3:0]; + + // shifter + wire [15:0] shifter_result; + wire shift_n; + wire shift_z; + wire shift_c; + wire shift_v; + shifter i_shifter ( + .a(qa), + .b(shifter_data), + .n_in(n), + .v_in(v), + .z_in(z), + .c_in(c), + .distance(shift_distance), + .func(ir_opcode[1:0]), + .result(shifter_result), + .n(shift_n), + .v(shift_v), + .z(shift_z), + .c(shift_c) + ); + + // memory data mux for lw/lb + reg [15:0] mem_data; + always @(*) + if ( ir_size ) + mem_data = din; + else + begin + if ( address[0] ) + mem_data = { 8'h00, din[7:0] }; + else + mem_data = { 8'h00, din[15:8] }; + end + + // register data + reg [15:0] reg_data; + always @(*) + case (state) + STATE_ALU : reg_data = alu_result; + STATE_SHIFT : reg_data = shifter_result; + STATE_JAL, + STATE_SWI : reg_data = pc; + default : reg_data = mem_data; + endcase + + // register writeback + reg reg_write; + always @(*) + case (state) + STATE_ALU, + STATE_SHIFT, + STATE_LOAD, + STATE_JAL, + STATE_SWI : reg_write = 1'b1; + default : reg_write = 1'b0; + endcase + + // override dst address for JAL to save 3 bits + reg [2:0] ra_dst; + always @(*) + if ( state == STATE_JAL ) + ra_dst = 3'd6; // hard linked register + else + ra_dst = ir_dst; + + // register file + wire [15:0] qa, qb; + regfile8x16 i_regfile ( + .clock(clk), + .data(reg_data), + .rdaddress_a(ir_dst), + .rdaddress_b(ir_src), + .wraddress(ra_dst), + .wren(reg_write&clk_en), + .qa(qa), + .qb(qb) + ); + + // flags + reg i, next_i; + reg n, next_n; + reg v, next_v; + reg z, next_z; + reg c, next_c; + always @(*) + case (state) + STATE_ALU : begin + next_i = i; + next_n = alu_n; + next_v = alu_v; + next_z = alu_z; + next_c = alu_c; + end + STATE_SHIFT : begin + next_i = i; + next_n = shift_n; + next_v = shift_v; + next_z = shift_z; + next_c = shift_c; + end + STATE_MOVSR : begin + 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_v = (v & ~ir_imm8[2]) | ( ir_imm8[7] & ir_imm8[2]); + next_z = (z & ~ir_imm8[1]) | ( ir_imm8[7] & ir_imm8[1]); + next_c = (c & ~ir_imm8[0]) | ( ir_imm8[7] & ir_imm8[0]); + end + STATE_INTREQ : begin + next_i = 1'b0; // disable interrupts + next_n = n; + next_v = v; + next_z = z; + next_c = c; + end + STATE_RFE : begin + next_i = esr[4]; + next_n = esr[3]; + next_v = esr[2]; + next_z = esr[1]; + next_c = esr[0]; + end + default : begin + next_i = i; + next_n = n; + next_v = v; + next_z = z; + next_c = c; + end + endcase + + // synchronous writeback + always @(posedge clk or negedge reset_n) + if (!reset_n) + begin + state <= STATE_FETCH; + ir <= 16'd0; + pc <= 16'd0; + i <= 1'b1; // TEST: enable interrupts + n <= 1'b0; + v <= 1'b0; + z <= 1'b0; + c <= 1'b0; + epc <= 16'd0; + esr <= 5'd0; + end + else if ( clk_en ) + begin + state <= next_state; + ir <= next_ir; + pc <= next_pc; + i <= next_i; + n <= next_n; + v <= next_v; + z <= next_z; + c <= next_c; + epc <= next_epc; + esr <= next_esr; + end +endmodule
cpu.v Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: cpu16.v =================================================================== --- cpu16.v (nonexistent) +++ cpu16.v (revision 2) @@ -0,0 +1,512 @@ +/* + * None pipelined, 3-state, 16-bit CPU + * + * Copyright (C) 2019, Yvo Zoer + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +module cpu16 ( + clk, + reset_n, + clk_en, + address, + din, + dout, + cs_n, + oe_n, + we_n, + ub_n, + lb_n, + irq, // combined interrupt request from intc + busreq, + busack + ); + + input clk; + input reset_n; + output [15:0] address; + input clk_en; + input [15:0] din; + output [15:0] dout; + output cs_n; + output oe_n; + output we_n; + output ub_n; + output lb_n; + input irq; + input busreq; + output busack; + + // alu + parameter OP_SUB = 5'd0; // ok + parameter OP_SBC = 5'd1; // ok + parameter OP_ADD = 5'd2; + parameter OP_ADC = 5'd3; + parameter OP_CMP = 5'd4; + parameter OP_AND = 5'd5; // ok + parameter OP_OR = 5'd6; // ok + parameter OP_XOR = 5'd7; // ok + + // alu immediate + parameter OP_SUBI = 5'd8; // ok + parameter OP_SBCI = 5'd9; // ok + parameter OP_ADDI = 5'd10; // ok + parameter OP_ADCI = 5'd11; // ok + parameter OP_CMPI = 5'd12; + parameter OP_ANDI = 5'd13; // ok + parameter OP_ORI = 5'd14; // ok + parameter OP_XORI = 5'd15; // ok + + // shifter + load + parameter OP_MOV = 5'd16; + parameter OP_SRAV = 5'd17; + parameter OP_SLLV = 5'd18; + parameter OP_LD = 5'd19; + + // shifter immediate + store + parameter OP_LUI = 5'd20; + parameter OP_SRA = 5'd21; + parameter OP_SLL = 5'd22; + parameter OP_ST = 5'd23; + + // jump + parameter OP_J = 5'd24; + parameter OP_JAL = 5'd25; + parameter OP_JR = 5'd26; + parameter OP_JALR = 5'd27; + + // conditional branch + parameter OP_BXX = 5'd28; + parameter OP_MSR = 5'd29; + parameter OP_RFE = 5'd30; + parameter OP_SWI = 5'd31; + + // states + parameter STATE_FETCH = 4'h0; + parameter STATE_DECODE = 4'h1; + parameter STATE_ALU = 4'h2; + parameter STATE_SHIFT = 4'h3; + parameter STATE_LOAD = 4'h4; + parameter STATE_STORE = 4'h5; + parameter STATE_J = 4'h6; + parameter STATE_JAL = 4'h7; + parameter STATE_BRANCH = 4'h8; + parameter STATE_MOVSR = 4'h9; + parameter STATE_RFE = 4'ha; + parameter STATE_SWI = 4'hb; + parameter STATE_INTREQ = 4'hc; + parameter STATE_BUSREQ = 4'hd; + + // instruction register wires + wire [4:0] ir_opcode = ir[15:11]; + wire [2:0] ir_dst = ir[10:8]; + wire [2:0] ir_src = ir[7:5]; + wire ir_size = ir[4]; // byte/word flag + 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 [10:0] ir_imm11 = ir[10:0]; // unconditional branch + + // busack valid once we're in the busreq state + reg busack; + always @(*) + if ( state == STATE_BUSREQ ) + busack = 1'b1; + else + busack = 1'b0; + +// chip-select + reg cs_n; + always @(*) + case (state) + STATE_FETCH, + STATE_LOAD, + STATE_STORE : cs_n = 1'b0; + default : cs_n = 1'b1; + endcase + + // output enable + reg oe_n; + always @(*) + case (state) + STATE_FETCH, + STATE_LOAD : oe_n = 1'b0; + default : oe_n = 1'b1; + endcase + // memory write signal + reg we_n; + always @(posedge clk) + if ( state == STATE_STORE ) + we_n <= clk_en; + else + we_n <= 1'b1; + + // upper / lower byte write/read enable + // NOTE: could integrate dout here as well.. + reg ub_n; + reg lb_n; + always @(*) + if ( state == STATE_STORE ) + begin + if ( ir_size ) + begin // word + ub_n = 1'b0; + lb_n = 1'b0; + end + else + begin // byte + if ( address[0] ) + begin + ub_n = 1'b1; + lb_n = 1'b0; + end + else + begin + ub_n = 1'b0; + lb_n = 1'b1; + end + end + end + else + begin // word access for everything else + ub_n = 1'b0; + lb_n = 1'b0; + end + + // data output logic + reg [15:0] dout; + always @(*) + if ( ir_size ) + dout = qa; // word + else + begin + if ( address[0] ) + dout = { 8'h00, qa[7:0] }; + else + dout = { qa[7:0], 8'h00 }; + end + + // address mux + reg [15:0] address; + always @(*) + case (state) + STATE_LOAD, + STATE_STORE : address = qb + ir_imm4; + default : address = pc; // { pc[15:1], 1'b0 }; + endcase + + // main state machine + reg [3:0] state, next_state; + always @(*) + case (state) + STATE_FETCH : next_state = STATE_DECODE; + STATE_DECODE : begin + casex (ir_opcode) + 5'b0xxxx : next_state = STATE_ALU; // sub/sbc/add/adc/and/or/xor/cmp + 5'b10x0x, + 5'b10x10 : next_state = STATE_SHIFT; + 5'b10011 : next_state = STATE_LOAD; + 5'b10111 : next_state = STATE_STORE; + 5'b110x0 : next_state = STATE_J; // 24/26 + 5'b110x1 : next_state = STATE_JAL; // 25/27 + 5'b11100 : next_state = STATE_BRANCH; + 5'b11101 : next_state = STATE_MOVSR; + 5'b11110 : next_state = STATE_RFE; + 5'b11111 : next_state = STATE_SWI; + default : next_state = STATE_FETCH; + endcase + end + STATE_INTREQ : next_state = STATE_FETCH; + STATE_BUSREQ : begin + if ( busreq ) + next_state = STATE_BUSREQ; + else + next_state = STATE_FETCH; // will miss interrupt when coming out of busreq (STATE_NOP?) + end + default : begin + if ( busreq ) + next_state = STATE_BUSREQ; + else if ( irq & i ) // only fires when interrupt enable is set (i = 1) + next_state = STATE_INTREQ; + else + next_state = STATE_FETCH; + end + endcase + + // instruction register + reg [15:0] ir, next_ir; + always @(*) + if ( state == STATE_FETCH ) + next_ir = din; + else + next_ir = ir; + + // exception pc- and status register + reg [15:0] epc, next_epc; + reg [4:0] esr, next_esr; + always @(*) + case (state) + STATE_INTREQ : begin + next_epc = pc; + next_esr = { i,n,v,z,c }; + end + default : begin + next_epc = epc; + next_esr = esr; + end + endcase + + // source data for program counter ( register / immediate ) + reg [15:0] pc_data; + always @(*) + if ( ir_opcode[1] ) // immediate for PC + pc_data = qb; //{ qb[15:1], 1'b0 }; // TEST: jr/jalr + else + pc_data = pc + { { 4 { ir_imm11[10] } }, ir_imm11[10:0], 1'b0 }; // TEST: j/jal doubled for jumps + + // condition check + reg condition_true; + always @(*) + case (ir_dst) + 3'd0 : condition_true = z; + 3'd1 : condition_true = ~z; + 3'd2 : condition_true = ~n; + 3'd3 : condition_true = n; + 3'd4 : condition_true = ~c; + 3'd5 : condition_true = c; + 3'd6 : condition_true = ~v; + 3'd7 : condition_true = v; + endcase + + // program counter + reg [15:0] pc, next_pc; + always @(*) + case (state) + STATE_FETCH : next_pc = pc + 16'd2; + STATE_SWI : next_pc = { ir_imm8, 1'b0 }; + STATE_J, + STATE_JAL : next_pc = pc_data; + STATE_BRANCH : begin + if ( condition_true ) + next_pc = pc + { { 7 { ir_imm8[7] } }, ir_imm8[7:0], 1'b0 }; + else + next_pc = pc; + end + STATE_INTREQ : next_pc = 16'h0002; // interrupt vector appears at 0x0002 + STATE_RFE : next_pc = epc; + default : next_pc = pc; + endcase + + // alu data mux + reg [15:0] alu_data; + always @(*) + if (ir_opcode[3]) // immediate + alu_data = { 8'h00, ir_imm8 }; + else + alu_data = qb; // register + + // alu + wire [15:0] alu_result; + wire alu_n; + wire alu_v; + wire alu_z; + wire alu_c; + alu i_alu ( + .a(qa), + .b(alu_data), + .c_in(c), + .func(ir_opcode[2:0]), + .result(alu_result), + .n(alu_n), + .v(alu_v), + .z(alu_z), + .c(alu_c) + ); + + // shifter data mux + reg [15:0] shifter_data; + always @(*) + if ( ir_opcode[2] ) // immediate + shifter_data = { ir_imm8, 8'h00 }; // lui from instruction word + else + shifter_data = qb; // mov + + // shifter distance -- roll into b argument inside shifter? + reg [3:0] shift_distance; + always @(*) + if ( ir_opcode[2] ) + shift_distance = ir_imm4; + else + shift_distance = qb[3:0]; + + // shifter + wire [15:0] shifter_result; + wire shift_n; + wire shift_z; + wire shift_c; + wire shift_v; + shifter i_shifter ( + .a(qa), + .b(shifter_data), + .n_in(n), + .v_in(v), + .z_in(z), + .c_in(c), + .distance(shift_distance), + .func(ir_opcode[1:0]), + .result(shifter_result), + .n(shift_n), + .v(shift_v), + .z(shift_z), + .c(shift_c) + ); + + // memory data mux for lw/lb + reg [15:0] mem_data; + always @(*) + if ( ir_size ) + mem_data = din; + else + begin + if ( address[0] ) + mem_data = { 8'h00, din[7:0] }; + else + mem_data = { 8'h00, din[15:8] }; + end + + // register data + reg [15:0] reg_data; + always @(*) + case (state) + STATE_ALU : reg_data = alu_result; + STATE_SHIFT : reg_data = shifter_result; + STATE_JAL, + STATE_SWI : reg_data = pc; + default : reg_data = mem_data; + endcase + + // register writeback + reg reg_write; + always @(*) + case (state) + STATE_ALU, + STATE_SHIFT, + STATE_LOAD, + STATE_JAL, + STATE_SWI : reg_write = 1'b1; + default : reg_write = 1'b0; + endcase + + // override dst address for JAL to save 3 bits + reg [2:0] ra_dst; + always @(*) + if ( state == STATE_JAL ) + ra_dst = 3'd6; // hard linked register + else + ra_dst = ir_dst; + + // register file + wire [15:0] qa, qb; + regfile8x16 i_regfile ( + .clock(clk), + .data(reg_data), + .rdaddress_a(ir_dst), + .rdaddress_b(ir_src), + .wraddress(ra_dst), + .wren(reg_write&clk_en), + .qa(qa), + .qb(qb) + ); + + // flags + reg i, next_i; + reg n, next_n; + reg v, next_v; + reg z, next_z; + reg c, next_c; + always @(*) + case (state) + STATE_ALU : begin + next_i = i; + next_n = alu_n; + next_v = alu_v; + next_z = alu_z; + next_c = alu_c; + end + STATE_SHIFT : begin + next_i = i; + next_n = shift_n; + next_v = shift_v; + next_z = shift_z; + next_c = shift_c; + end + STATE_MOVSR : begin + 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_v = (v & ~ir_imm8[2]) | ( ir_imm8[7] & ir_imm8[2]); + next_z = (z & ~ir_imm8[1]) | ( ir_imm8[7] & ir_imm8[1]); + next_c = (c & ~ir_imm8[0]) | ( ir_imm8[7] & ir_imm8[0]); + end + STATE_INTREQ : begin + next_i = 1'b0; // disable interrupts + next_n = n; + next_v = v; + next_z = z; + next_c = c; + end + STATE_RFE : begin + next_i = esr[4]; + next_n = esr[3]; + next_v = esr[2]; + next_z = esr[1]; + next_c = esr[0]; + end + default : begin + next_i = i; + next_n = n; + next_v = v; + next_z = z; + next_c = c; + end + endcase + + // synchronous writeback + always @(posedge clk or negedge reset_n) + if (!reset_n) + begin + state <= STATE_FETCH; + ir <= 16'd0; + pc <= 16'd0; + i <= 1'b1; // TEST: enable interrupts + n <= 1'b0; + v <= 1'b0; + z <= 1'b0; + c <= 1'b0; + epc <= 16'd0; + esr <= 5'd0; + end + else if ( clk_en ) + begin + state <= next_state; + ir <= next_ir; + pc <= next_pc; + i <= next_i; + n <= next_n; + v <= next_v; + z <= next_z; + c <= next_c; + epc <= next_epc; + esr <= next_esr; + end +endmodule
cpu16.v Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: regfile8x16.v =================================================================== --- regfile8x16.v (nonexistent) +++ regfile8x16.v (revision 2) @@ -0,0 +1,192 @@ +// megafunction wizard: %RAM: 3-PORT% +// GENERATION: STANDARD +// VERSION: WM1.0 +// MODULE: alt3pram + +// ============================================================ +// File Name: regfile8x16.v +// Megafunction Name(s): +// alt3pram +// +// Simulation Library Files(s): +// altera_mf +// ============================================================ +// ************************************************************ +// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! +// +// 9.0 Build 235 06/17/2009 SP 2 SJ Web Edition +// ************************************************************ + + +//Copyright (C) 1991-2009 Altera Corporation +//Your use of Altera Corporation's design tools, logic functions +//and other software and tools, and its AMPP partner logic +//functions, and any output files from any of the foregoing +//(including device programming or simulation files), and any +//associated documentation or information are expressly subject +//to the terms and conditions of the Altera Program License +//Subscription Agreement, Altera MegaCore Function License +//Agreement, or other applicable license agreement, including, +//without limitation, that your use is for the sole purpose of +//programming logic devices manufactured by Altera and sold by +//Altera or its authorized distributors. Please refer to the +//applicable agreement for further details. + + +// synopsys translate_off +`timescale 1 ps / 1 ps +// synopsys translate_on +module regfile8x16 ( + clock, + data, + rdaddress_a, + rdaddress_b, + wraddress, + wren, + qa, + qb); + + input clock; + input [15:0] data; + input [2:0] rdaddress_a; + input [2:0] rdaddress_b; + input [2:0] wraddress; + input wren; + output [15:0] qa; + output [15:0] qb; +`ifndef ALTERA_RESERVED_QIS +// synopsys translate_off +`endif + tri0 wren; +`ifndef ALTERA_RESERVED_QIS +// synopsys translate_on +`endif + + wire [15:0] sub_wire0; + wire [15:0] sub_wire1; + wire [15:0] qa = sub_wire0[15:0]; + wire [15:0] qb = sub_wire1[15:0]; + + alt3pram alt3pram_component ( + .wren (wren), + .inclock (clock), + .data (data), + .rdaddress_a (rdaddress_a), + .wraddress (wraddress), + .rdaddress_b (rdaddress_b), + .qa (sub_wire0), + .qb (sub_wire1) + // synopsys translate_off + , + .aclr (), + .inclocken (), + .outclock (), + .outclocken (), + .rden_a (), + .rden_b () + // synopsys translate_on + ); + defparam + alt3pram_component.indata_aclr = "OFF", + alt3pram_component.indata_reg = "INCLOCK", + alt3pram_component.intended_device_family = "Cyclone II", + alt3pram_component.lpm_type = "alt3pram", + alt3pram_component.outdata_aclr_a = "OFF", + alt3pram_component.outdata_aclr_b = "OFF", + alt3pram_component.outdata_reg_a = "UNREGISTERED", + alt3pram_component.outdata_reg_b = "UNREGISTERED", + alt3pram_component.rdaddress_aclr_a = "OFF", + alt3pram_component.rdaddress_aclr_b = "OFF", + alt3pram_component.rdaddress_reg_a = "INCLOCK", + alt3pram_component.rdaddress_reg_b = "INCLOCK", + alt3pram_component.rdcontrol_aclr_a = "OFF", + alt3pram_component.rdcontrol_aclr_b = "OFF", + alt3pram_component.rdcontrol_reg_a = "UNREGISTERED", + alt3pram_component.rdcontrol_reg_b = "UNREGISTERED", + alt3pram_component.width = 16, + alt3pram_component.widthad = 3, + alt3pram_component.write_aclr = "OFF", + alt3pram_component.write_reg = "INCLOCK"; + + +endmodule + +// ============================================================ +// CNX file retrieval info +// ============================================================ +// Retrieval info: PRIVATE: BlankMemory NUMERIC "1" +// Retrieval info: PRIVATE: CLRdata NUMERIC "0" +// Retrieval info: PRIVATE: CLRqa NUMERIC "0" +// Retrieval info: PRIVATE: CLRqb NUMERIC "0" +// Retrieval info: PRIVATE: CLRrdaddress_a NUMERIC "0" +// Retrieval info: PRIVATE: CLRrdaddress_b NUMERIC "0" +// Retrieval info: PRIVATE: CLRrren_a NUMERIC "0" +// Retrieval info: PRIVATE: CLRrren_b NUMERIC "0" +// Retrieval info: PRIVATE: CLRwrite NUMERIC "0" +// Retrieval info: PRIVATE: Clock NUMERIC "0" +// Retrieval info: PRIVATE: INIT_FILE_LAYOUT STRING "PORT_A" +// Retrieval info: PRIVATE: INIT_TO_SIM_X NUMERIC "0" +// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone II" +// Retrieval info: PRIVATE: JTAG_ENABLED NUMERIC "0" +// Retrieval info: PRIVATE: JTAG_ID STRING "NONE" +// Retrieval info: PRIVATE: MAXIMUM_DEPTH NUMERIC "0" +// Retrieval info: PRIVATE: MIFfilename STRING "" +// Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "0" +// Retrieval info: PRIVATE: REGdata NUMERIC "1" +// Retrieval info: PRIVATE: REGqa NUMERIC "0" +// Retrieval info: PRIVATE: REGqb NUMERIC "0" +// Retrieval info: PRIVATE: REGrdaddress_a NUMERIC "1" +// Retrieval info: PRIVATE: REGrdaddress_b NUMERIC "1" +// Retrieval info: PRIVATE: REGrren_a NUMERIC "0" +// Retrieval info: PRIVATE: REGrren_b NUMERIC "0" +// Retrieval info: PRIVATE: REGwrite NUMERIC "1" +// Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0" +// Retrieval info: PRIVATE: WidthAddr NUMERIC "3" +// Retrieval info: PRIVATE: WidthData NUMERIC "16" +// Retrieval info: PRIVATE: enable NUMERIC "0" +// Retrieval info: PRIVATE: rden_a NUMERIC "0" +// Retrieval info: PRIVATE: rden_b NUMERIC "0" +// Retrieval info: CONSTANT: INDATA_ACLR STRING "OFF" +// Retrieval info: CONSTANT: INDATA_REG STRING "INCLOCK" +// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone II" +// Retrieval info: CONSTANT: LPM_TYPE STRING "alt3pram" +// Retrieval info: CONSTANT: OUTDATA_ACLR_A STRING "OFF" +// Retrieval info: CONSTANT: OUTDATA_ACLR_B STRING "OFF" +// Retrieval info: CONSTANT: OUTDATA_REG_A STRING "UNREGISTERED" +// Retrieval info: CONSTANT: OUTDATA_REG_B STRING "UNREGISTERED" +// Retrieval info: CONSTANT: RDADDRESS_ACLR_A STRING "OFF" +// Retrieval info: CONSTANT: RDADDRESS_ACLR_B STRING "OFF" +// Retrieval info: CONSTANT: RDADDRESS_REG_A STRING "INCLOCK" +// Retrieval info: CONSTANT: RDADDRESS_REG_B STRING "INCLOCK" +// Retrieval info: CONSTANT: RDCONTROL_ACLR_A STRING "OFF" +// Retrieval info: CONSTANT: RDCONTROL_ACLR_B STRING "OFF" +// Retrieval info: CONSTANT: RDCONTROL_REG_A STRING "UNREGISTERED" +// Retrieval info: CONSTANT: RDCONTROL_REG_B STRING "UNREGISTERED" +// Retrieval info: CONSTANT: WIDTH NUMERIC "16" +// Retrieval info: CONSTANT: WIDTHAD NUMERIC "3" +// Retrieval info: CONSTANT: WRITE_ACLR STRING "OFF" +// Retrieval info: CONSTANT: WRITE_REG STRING "INCLOCK" +// Retrieval info: USED_PORT: clock 0 0 0 0 INPUT NODEFVAL clock +// Retrieval info: USED_PORT: data 0 0 16 0 INPUT NODEFVAL data[15..0] +// Retrieval info: USED_PORT: qa 0 0 16 0 OUTPUT NODEFVAL qa[15..0] +// Retrieval info: USED_PORT: qb 0 0 16 0 OUTPUT NODEFVAL qb[15..0] +// Retrieval info: USED_PORT: rdaddress_a 0 0 3 0 INPUT NODEFVAL rdaddress_a[2..0] +// Retrieval info: USED_PORT: rdaddress_b 0 0 3 0 INPUT NODEFVAL rdaddress_b[2..0] +// Retrieval info: USED_PORT: wraddress 0 0 3 0 INPUT NODEFVAL wraddress[2..0] +// Retrieval info: USED_PORT: wren 0 0 0 0 INPUT GND wren +// Retrieval info: CONNECT: @data 0 0 16 0 data 0 0 16 0 +// Retrieval info: CONNECT: qa 0 0 16 0 @qa 0 0 16 0 +// Retrieval info: CONNECT: qb 0 0 16 0 @qb 0 0 16 0 +// Retrieval info: CONNECT: @wraddress 0 0 3 0 wraddress 0 0 3 0 +// Retrieval info: CONNECT: @rdaddress_a 0 0 3 0 rdaddress_a 0 0 3 0 +// Retrieval info: CONNECT: @rdaddress_b 0 0 3 0 rdaddress_b 0 0 3 0 +// Retrieval info: CONNECT: @wren 0 0 0 0 wren 0 0 0 0 +// Retrieval info: CONNECT: @inclock 0 0 0 0 clock 0 0 0 0 +// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all +// Retrieval info: GEN_FILE: TYPE_NORMAL regfile8x16.v TRUE +// Retrieval info: GEN_FILE: TYPE_NORMAL regfile8x16.inc TRUE +// Retrieval info: GEN_FILE: TYPE_NORMAL regfile8x16.cmp FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL regfile8x16.bsf FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL regfile8x16_inst.v FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL regfile8x16_bb.v TRUE +// Retrieval info: LIB_FILE: altera_mf
regfile8x16.v Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: shifter.v =================================================================== --- shifter.v (nonexistent) +++ shifter.v (revision 2) @@ -0,0 +1,59 @@ +module shifter ( + a, + b, + n_in, + v_in, + z_in, + c_in, + distance, + func, + result, + n, + v, + z, + c + ); + + input signed [15:0] a,b; + input n_in; + input v_in; + input z_in; + input c_in; + input [3:0] distance; + input [1:0] func; + output [15:0] result; + output n,v,z,c; + + // hack / workaround to make sure carry / msb gets propagated correctly + wire signed [16:0] x = { a, c_in }; + + reg [15:0] result; + reg result_c; + always @(*) + case(func) + 2'd0 : { result_c, result } = { c_in, b }; // mov / lui + 2'd1 : { result, result_c } = x >>> distance; // sra + default : { result_c, result } = { c_in, a } << distance; // sll + endcase + + // flags + reg n,v,z,c; + always @(*) + begin + if ( func ) + begin // shifts update accordingly + n = result[15]; + z = ~|result; + c = result_c; + v = a[15] ^ result[15]; + end + else // mov / lui don't change flags as they're frequently used to create literals / masks / addresses + begin + n = n_in; + v = v_in; + z = z_in; + c = c_in; + end + end + +endmodule
shifter.v Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property

powered by: WebSVN 2.1.0

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