summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick McKinney <nick@kmonkey.net>2016-12-18 15:54:12 -0600
committerNick McKinney <nick@kmonkey.net>2016-12-18 15:54:12 -0600
commit9a8d8892361dcd16ad3801ce29e25516c8cd1019 (patch)
tree01f8cd27475fa5c9535b507d54eef7880f95a830
parent603bee2b743f1a72222fd8586fa809555f08ea77 (diff)
Add ALU stage and hook it up. It sort of works.
-rw-r--r--alu_stage.v107
-rw-r--r--ctrl_decode.v41
-rw-r--r--ctrl_encode.v41
-rw-r--r--decoder.v36
-rw-r--r--decoder_stage.v62
-rw-r--r--fetch_stage.v7
-rw-r--r--nqcpu.qsf8
-rw-r--r--nqcpu.v158
-rw-r--r--regFile.v22
9 files changed, 429 insertions, 53 deletions
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