From 9a8d8892361dcd16ad3801ce29e25516c8cd1019 Mon Sep 17 00:00:00 2001 From: Nick McKinney Date: Sun, 18 Dec 2016 15:54:12 -0600 Subject: Add ALU stage and hook it up. It sort of works. --- alu_stage.v | 107 ++++++++++++++++++++++++++++++++++++++ ctrl_decode.v | 41 +++++++++++++++ ctrl_encode.v | 41 +++++++++++++++ decoder.v | 36 ++++++++----- decoder_stage.v | 62 ++++++++++------------ fetch_stage.v | 7 ++- nqcpu.qsf | 8 ++- nqcpu.v | 158 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ regFile.v | 22 +++++++- 9 files changed, 429 insertions(+), 53 deletions(-) create mode 100644 alu_stage.v create mode 100644 ctrl_decode.v create mode 100644 ctrl_encode.v create mode 100644 nqcpu.v diff --git a/alu_stage.v b/alu_stage.v new file mode 100644 index 0000000..0ab5265 --- /dev/null +++ b/alu_stage.v @@ -0,0 +1,107 @@ +module alu_stage ( + input clk, + input en, + input [15:0] pc_in, + input [31:0] control_signals_in, + input [15:0] imm_in, + + // register file + output [2:0] rf_regA, + output [2:0] rf_regB, + output [2:0] rf_regDest, + output [15:0] rf_dataIn, + output rf_we, + output rf_hb, + output rf_lb, + input [15:0] rf_dataA, + input [15:0] rf_dataB, + + // memory interface + input [15:0] memData_in, // read in from memory + output reg [15:0] memData_out, // to write out to memory + + output reg [31:0] control_signals_out, + output reg [15:0] imm_out, + output reg [15:0] pc_out +); + + // decode signals + wire [3:0] aluOp_in; + wire [2:0] aluReg1_in; + wire [2:0] aluReg2_in; + wire [1:0] aluOpSource1_in; + wire [1:0] aluOpSource2_in; + wire aluDest_in; + wire [2:0] regDest_in; + wire regSetH_in; + wire regSetL_in; + wire [2:0] regAddr_in; + wire memReadB_in; + wire memReadW_in; + wire memWriteB_in; + wire memWriteW_in; + wire [4:0] setRegCond_in; + + ctrl_decode ctrl_decode_inst ( + .control_signals(control_signals_in), + + .aluOp(aluOp_in), + .aluReg1(aluReg1_in), + .aluReg2(aluReg2_in), + .aluOpSource1(aluOpSource1_in), // ALU first operand: 0 = reg, 1 = memory read, 2 = imm8, 3 = PC + .aluOpSource2(aluOpSource2_in), // ALU second operand: 0 = reg, 1 = ~reg, 2 = PC, 3 = ??? + .aluDest(aluDest_in), // 0 = reg, 1 = PC + + .regDest(regDest_in), + .regSetH(regSetH_in), + .regSetL(regSetL_in), + + .regAddr(regAddr_in), + .memReadB(memReadB_in), + .memReadW(memReadW_in), + .memWriteB(memWriteB_in), + .memWriteW(memWriteW_in), + + .setRegCond(setRegCond_in) // {should set when condition is true, Z doesn't matter, S doesn't matter, Z must be this, S must be this} + ); + + wire [15:0] aluSrc1; + assign aluSrc1 = + aluOpSource1_in == 2'h0 ? rf_dataA : + aluOpSource1_in == 2'h1 ? memData_in : + aluOpSource1_in == 2'h2 ? {imm_in} : pc_in; + + wire [15:0] aluSrc2; + assign aluSrc2 = + aluOpSource1_in == 2'h0 ? rf_dataB : + aluOpSource1_in == 2'h1 ? ~rf_dataIn : pc_in; + + wire [15:0] aluResult; + wire aluZero, aluCarry; + alu alu_inst ( + .op(aluOp_in), + .x(aluSrc1), + .y(aluSrc2), + .result(aluResult), + .zero(aluZero), + .carry(aluCarry) + ); + + assign rf_regA = aluReg1_in; + assign rf_regB = aluReg2_in; + assign rf_we = en & (regSetH_in | regSetL_in); + assign rf_hb = regSetH_in; + assign rf_lb = regSetL_in; + assign rf_dataIn = aluResult; + assign rf_regDest = regDest_in; + + always @(posedge clk) begin + if(en) begin + control_signals_out <= control_signals_in; + imm_out <= imm_in; + memData_out <= aluResult; + pc_out <= pc_in; + end + end + +endmodule diff --git a/ctrl_decode.v b/ctrl_decode.v new file mode 100644 index 0000000..cda670d --- /dev/null +++ b/ctrl_decode.v @@ -0,0 +1,41 @@ +module ctrl_decode ( + input [31:0] control_signals, + + output [3:0] aluOp, + output [2:0] aluReg1, + output [2:0] aluReg2, + output [1:0] aluOpSource1, // ALU first operand: 0 = reg, 1 = memory read, 2 = imm8, 3 = PC + output [1:0] aluOpSource2, // ALU second operand: 0 = reg, 1 = ~reg, 2 = PC, 3 = ??? + output aluDest, // 0 = reg, 1 = PC + + output [2:0] regDest, + output regSetH, + output regSetL, + + output [2:0] regAddr, + output memReadB, + output memReadW, + output memWriteB, + output memWriteW, + + output [4:0] setRegCond // {should set when condition is true, Z doesn't matter, S doesn't matter, Z must be this, S must be this} +); + + assign { + aluOp, + aluReg1, + aluReg2, + aluOpSource1, + aluOpSource2, + aluDest, + regDest, + regSetH, + regSetL, + regAddr, + memReadB, + memReadW, + memWriteB, + memWriteW, + setRegCond + } = control_signals; +endmodule diff --git a/ctrl_encode.v b/ctrl_encode.v new file mode 100644 index 0000000..6eb0635 --- /dev/null +++ b/ctrl_encode.v @@ -0,0 +1,41 @@ +module ctrl_encode ( + input [3:0] aluOp, + input [2:0] aluReg1, + input [2:0] aluReg2, + input [1:0] aluOpSource1, // ALU first operand: 0 = reg, 1 = memory read, 2 = imm8, 3 = PC + input [1:0] aluOpSource2, // ALU second operand: 0 = reg, 1 = ~reg, 2 = PC, 3 = ??? + input aluDest, // 0 = reg, 1 = PC + + input [2:0] regDest, + input regSetH, + input regSetL, + + input [2:0] regAddr, + input memReadB, + input memReadW, + input memWriteB, + input memWriteW, + + input [4:0] setRegCond, // {should set when condition is true, Z doesn't matter, S doesn't matter, Z must be this, S must be this} + + output [31:0] control_signals +); + + assign control_signals = { + aluOp, + aluReg1, + aluReg2, + aluOpSource1, + aluOpSource2, + aluDest, + regDest, + regSetH, + regSetL, + regAddr, + memReadB, + memReadW, + memWriteB, + memWriteW, + setRegCond + }; +endmodule diff --git a/decoder.v b/decoder.v index 63e4f1d..7599781 100644 --- a/decoder.v +++ b/decoder.v @@ -42,6 +42,7 @@ module decoder ( // instructions // add (reg0 <- reg1 + reg2) +// addpc (reg0 <- PC + imm8) // sub (reg0 <- reg1 - reg2) // mul (reg0 <- reg1 * reg2) // div (reg0 <- reg1 / reg2) @@ -72,6 +73,9 @@ module decoder ( // 1 10 xor // 1 11 ??? +// addpc +// 1000 + [reg0] + 0 + [imm] +// adds the immediate value (signed) to the current value of PC and puts the result in reg0 // shl/slr // 0001 + [reg0] + [dir] + [reg1] + [reg2] + [extend] @@ -120,23 +124,30 @@ module decoder ( // 0111 + 00000 + [reg1] + 00000 // basically moves reg1 to pc +// nop +// 1111 + xxxx xxxx xxxx + // instruction decode wire [3:0] which_instr = instr[15:12]; - wire instr_math, instr_shift, instr_notneg, instr_bts, instr_mov, instr_movimm, instr_branch, instr_jmp, instr_nop; - assign {instr_math, instr_shift, instr_notneg, instr_bts, instr_mov, instr_movimm, instr_branch, instr_jmp, instr_nop} = - which_instr == 4'h0 ? 9'b100000000 : - which_instr == 4'h1 ? 9'b010000000 : - which_instr == 4'h2 ? 9'b001000000 : - which_instr == 4'h3 ? 9'b000100000 : - which_instr == 4'h4 ? 9'b000010000 : - which_instr == 4'h5 ? 9'b000001000 : - which_instr == 4'h6 ? 9'b000000100 : - which_instr == 4'h7 ? 9'b000000010 : 9'b000000001; + wire instr_math, instr_shift, instr_notneg, instr_bts, instr_mov, instr_movimm, instr_branch, instr_jmp, instr_addpc, instr_nop; + assign {instr_math, instr_shift, instr_notneg, instr_bts, instr_mov, instr_movimm, instr_branch, instr_jmp, instr_addpc, instr_nop} = + which_instr == 4'h0 ? 10'b1000000000 : + which_instr == 4'h1 ? 10'b0100000000 : + which_instr == 4'h2 ? 10'b0010000000 : + which_instr == 4'h3 ? 10'b0001000000 : + which_instr == 4'h4 ? 10'b0000100000 : + which_instr == 4'h5 ? 10'b0000010000 : + which_instr == 4'h6 ? 10'b0000001000 : + which_instr == 4'h7 ? 10'b0000000100 : + which_instr == 4'h8 ? 10'b0000000010 : 10'b0000000001; // src/dest registers wire [2:0] reg0 = instr[11:9]; wire [2:0] reg1 = instr[7:5]; wire [2:0] reg2 = instr[4:2]; + + wire [7:0] imm_param = instr[7:0]; + wire [15:0] ext_imm_param = {{8{instr[7]}}, instr[7:0]}; // sign-extended immediate parameter // for instr_math wire [2:0] math_op = {instr[8], instr[1:0]}; @@ -156,7 +167,7 @@ module decoder ( // for instr_movimm wire movimm_high = instr[8]; - wire [7:0] movimm_imm = instr[7:0]; + wire [7:0] movimm_imm = imm_param; // for instr_branch wire [2:0] branch_cond = instr[11:9]; @@ -224,7 +235,8 @@ module decoder ( assign imm = instr_notneg ? {15'b0, notneg_is_neg} : - instr_branch ? {8'b0, branch_offset} : + instr_branch ? ext_imm_param : + instr_addpc ? ext_imm_param : {movimm_imm, movimm_imm}; endmodule diff --git a/decoder_stage.v b/decoder_stage.v index 18ed195..aad5f56 100644 --- a/decoder_stage.v +++ b/decoder_stage.v @@ -3,27 +3,11 @@ module decoder_stage ( input en, input [15:0] instr_in, + input [15:0] pc_in, - output reg [3:0] aluOp_out, - output reg [2:0] aluReg1_out, - output reg [2:0] aluReg2_out, - output reg [1:0] aluOpSource1_out, // ALU first operand: 0 = reg, 1 = memory read, 2 = imm8, 3 = PC - output reg [1:0] aluOpSource2_out, // ALU second operand: 0 = reg, 1 = ~reg, 2 = PC, 3 = ??? - output reg aluDest_out, // 0 = reg, 1 = PC - - output reg [2:0] regDest_out, - output reg regSetH_out, - output reg regSetL_out, - - output reg [2:0] regAddr_out, - output reg memReadB_out, - output reg memReadW_out, - output reg memWriteB_out, - output reg memWriteW_out, - - output reg [4:0] setRegCond_out, // {should set when condition is true, Z doesn't matter, S doesn't matter, Z must be this, S must be this} - - output reg [15:0] imm_out + output reg [31:0] control_signals_out, + output reg [15:0] imm_out, + output reg [15:0] pc_out ); wire [3:0] aluOp_next; @@ -63,24 +47,32 @@ module decoder_stage ( .imm(imm_next) ); + wire [31:0] control_signals_next; + + ctrl_encode encode_inst ( + .aluOp(aluOp_next), + .aluReg1(aluReg1_next), + .aluReg2(aluReg2_next), + .aluOpSource1(aluOpSource1_next), + .aluOpSource2(aluOpSource2_next), + .aluDest(aluDest_next), + .regDest(regDest_next), + .regSetH(regSetH_next), + .regSetL(regSetL_next), + .regAddr(regAddr_next), + .memReadB(memReadB_next), + .memReadW(memReadW_next), + .memWriteB(memWriteB_next), + .memWriteW(memWriteW_next), + .setRegCond(setRegCond_next), + .control_signals(control_signals_next) + ); + always @(posedge clk) begin if(en) begin - aluOp_out <= aluOp_next; - aluReg1_out <= aluReg1_next; - aluReg2_out <= aluReg2_next; - aluOpSource1_out <= aluOpSource1_next; - aluOpSource2_out <= aluOpSource2_next; - aluDest_out <= aluDest_next; - regDest_out <= regDest_next; - regSetH_out <= regSetH_next; - regSetL_out <= regSetL_next; - regAddr_out <= regAddr_next; - memReadB_out <= memReadB_next; - memReadW_out <= memReadW_next; - memWriteB_out <= memWriteB_next; - memWriteW_out <= memWriteW_next; - setRegCond_out <= setRegCond_next; + control_signals_out <= control_signals_next; imm_out <= imm_next; + pc_out <= pc_in; end end endmodule diff --git a/fetch_stage.v b/fetch_stage.v index 03621c3..2fce850 100644 --- a/fetch_stage.v +++ b/fetch_stage.v @@ -5,7 +5,8 @@ module fetch_stage ( input [15:0] addr_in, - output reg [15:0] instr_out + output reg [15:0] instr_out, + output reg [15:0] pc_out ); always @(posedge clk) begin @@ -23,8 +24,10 @@ module fetch_stage ( 15'h6: instr_out <= 16'b0100_000_0_011_00100; // mov r0,r3 15'h7: instr_out <= 16'b0000_100_1_100_100_10; // xor r4,r4,r4 15'h8: instr_out <= 16'b0111_00000_100_00000; // jmp r4 - default: instr_out <= 16'b1000_000000000000; // nop + default: instr_out <= 16'b1111_000000000000; // nop endcase + + pc_out <= addr_in; end else begin ready <= 1'b0; diff --git a/nqcpu.qsf b/nqcpu.qsf index a96e544..d196471 100644 --- a/nqcpu.qsf +++ b/nqcpu.qsf @@ -38,7 +38,7 @@ set_global_assignment -name FAMILY "Cyclone II" set_global_assignment -name DEVICE EP2C20F484C7 -set_global_assignment -name TOP_LEVEL_ENTITY decoder_stage +set_global_assignment -name TOP_LEVEL_ENTITY nqcpu set_global_assignment -name ORIGINAL_QUARTUS_VERSION "13.0 SP1" set_global_assignment -name PROJECT_CREATION_TIME_DATE "22:25:59 NOVEMBER 17, 2016" set_global_assignment -name LAST_QUARTUS_VERSION "13.0 SP1" @@ -56,8 +56,12 @@ set_global_assignment -name VERILOG_FILE shifter.v set_global_assignment -name VERILOG_FILE shifter_tb.v set_global_assignment -name VERILOG_FILE alu_tb.v set_global_assignment -name VERILOG_FILE decoder_stage.v +set_global_assignment -name VERILOG_FILE fetch_stage.v +set_global_assignment -name VERILOG_FILE ctrl_decode.v +set_global_assignment -name VERILOG_FILE ctrl_encode.v +set_global_assignment -name VERILOG_FILE nqcpu.v set_global_assignment -name PARTITION_NETLIST_TYPE SOURCE -section_id Top set_global_assignment -name PARTITION_FITTER_PRESERVATION_LEVEL PLACEMENT_AND_ROUTING -section_id Top set_global_assignment -name PARTITION_COLOR 16764057 -section_id Top -set_global_assignment -name VERILOG_FILE fetch_stage.v +set_global_assignment -name VERILOG_FILE alu_stage.v set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top \ No newline at end of file diff --git a/nqcpu.v b/nqcpu.v new file mode 100644 index 0000000..7656159 --- /dev/null +++ b/nqcpu.v @@ -0,0 +1,158 @@ +module nqcpu ( + input clk, + + output [15:0] debugPC, + output [3:0] debugAluOp, + output [2:0] debugAluReg1, + output [2:0] debugAluReg2, + output [1:0] debugAluOpSource1, // ALU first operand: 0 = reg, 1 = memory read, 2 = imm8, 3 = PC + output [1:0] debugAluOpSource2, // ALU second operand: 0 = reg, 1 = ~reg, 2 = PC, 3 = ??? + output debugAluDest, // 0 = reg, 1 = PC + + output [2:0] debugRegDest, + output debugRegSetH, + output debugRegSetL, + + output [2:0] debugRegAddr, + output debugMemReadB, + output debugMemReadW, + output debugMemWriteB, + output debugMemWriteW, + + output [4:0] debugSetRegCond, // {should set when condition is true, Z doesn't matter, S doesn't matter, Z must be this, S must be this} + + output [15:0] dbg_r0, + output [15:0] dbg_r1, + output [15:0] dbg_r2, + output [15:0] dbg_r3, + output [15:0] dbg_r4, + output [15:0] dbg_r5, + output [15:0] dbg_r6, + output [15:0] dbg_r7 +); + + reg [15:0] pc; + + initial begin + pc = 16'h0; + end + + wire fetch_ready; + wire [15:0] fetched_instr; + wire [15:0] pc_from_fetch; + fetch_stage fetch_inst ( + .clk(clk), + .en(1'b1), + .addr_in(pc), + .ready(fetch_ready), + .instr_out(fetched_instr), + .pc_out(pc_from_fetch) + ); + + always @(posedge clk) begin + if(fetch_ready) begin + pc <= pc + 16'h2; + end + end + + wire [31:0] ctrl_from_decoder; + wire [15:0] imm_from_decoder; + wire [15:0] pc_from_decoder; + + decoder_stage decoder_inst ( + .clk(clk), + .en(fetch_ready), + .instr_in(fetched_instr), + .pc_in(pc_from_fetch), + .control_signals_out(ctrl_from_decoder), + .imm_out(imm_from_decoder), + .pc_out(pc_from_decoder) + ); + + wire [2:0] rf_regA; + wire [2:0] rf_regB; + wire [2:0] rf_regDest; + wire [15:0] rf_dataIn; + wire rf_we; + wire rf_hb; + wire rf_lb; + wire [15:0] rf_dataA; + wire [15:0] rf_dataB; + regFile regFile_inst ( + .clk(clk), + .regA(rf_regA), + .regB(rf_regB), + .regDest(rf_regDest), + .dataIn(rf_dataIn), + .we(rf_we), + .hb(rf_hb), + .lb(rf_lb), + .dataA(rf_dataA), + .dataB(rf_dataB), + + .dbg_r0(dbg_r0), + .dbg_r1(dbg_r1), + .dbg_r2(dbg_r2), + .dbg_r3(dbg_r3), + .dbg_r4(dbg_r4), + .dbg_r5(dbg_r5), + .dbg_r6(dbg_r6), + .dbg_r7(dbg_r7) + ); + + wire [31:0] ctrl_from_alu; + wire [15:0] imm_from_alu; + wire [15:0] pc_from_alu; + alu_stage alu_inst ( + .clk(clk), + .en(1'b1), + .pc_in(pc_from_decoder), + .control_signals_in(ctrl_from_decoder), + .imm_in(imm_from_decoder), + + // register file + .rf_regA(rf_regA), + .rf_regB(rf_regB), + .rf_regDest(rf_regDest), + .rf_dataIn(rf_dataIn), + .rf_we(rf_we), + .rf_hb(rf_hb), + .rf_lb(rf_lb), + .rf_dataA(rf_dataA), + .rf_dataB(rf_dataB), + + // memory interface + .memData_in(16'hDEAD), // read in from memory + //.memData_out(??), // to write out to memory + + .control_signals_out(ctrl_from_alu), + .imm_out(imm_from_alu), + .pc_out(pc_from_alu) + ); + + ctrl_decode debug_decode ( + .control_signals(ctrl_from_alu), + + .aluOp(debugAluOp), + .aluReg1(debugAluReg1), + .aluReg2(debugAluReg2), + .aluOpSource1(debugAluOpSource1), + .aluOpSource2(debugAluOpSource2), + .aluDest(debugAluDest), + + .regDest(debugRegDest), + .regSetH(debugRegSetH), + .regSetL(debugRegSetL), + + .regAddr(debugRegAddr), + .memReadB(debugMemReadB), + .memReadW(debugMemReadW), + .memWriteB(debugMemWriteB), + .memWriteW(debugMemWriteW), + + .setRegCond(debugSetRegCond) + ); + + assign debugPC = pc_from_alu; + +endmodule diff --git a/regFile.v b/regFile.v index 4331adc..7410847 100644 --- a/regFile.v +++ b/regFile.v @@ -8,10 +8,19 @@ module regFile ( input hb, input lb, output [15:0] dataA, - output [15:0] dataB + output [15:0] dataB, + + output [15:0] dbg_r0, + output [15:0] dbg_r1, + output [15:0] dbg_r2, + output [15:0] dbg_r3, + output [15:0] dbg_r4, + output [15:0] dbg_r5, + output [15:0] dbg_r6, + output [15:0] dbg_r7 ); - reg [15:0] register[7]; + reg [15:0] register[8]; assign dataA = register[regA]; assign dataB = register[regB]; @@ -24,4 +33,13 @@ module regFile ( }; end end + + assign dbg_r0 = register[0]; + assign dbg_r1 = register[1]; + assign dbg_r2 = register[2]; + assign dbg_r3 = register[3]; + assign dbg_r4 = register[4]; + assign dbg_r5 = register[5]; + assign dbg_r6 = register[6]; + assign dbg_r7 = register[7]; endmodule -- cgit v1.2.3