summaryrefslogtreecommitdiff
path: root/datapath
diff options
context:
space:
mode:
Diffstat (limited to 'datapath')
-rw-r--r--datapath/v0.1/Makefile17
-rw-r--r--datapath/v0.1/data_path.v129
-rw-r--r--datapath/v0.1/test_data_path.v158
3 files changed, 304 insertions, 0 deletions
diff --git a/datapath/v0.1/Makefile b/datapath/v0.1/Makefile
new file mode 100644
index 0000000..b4aa522
--- /dev/null
+++ b/datapath/v0.1/Makefile
@@ -0,0 +1,17 @@
+
+I_INSTRMEM=-I../../instrmem/v0.1 ../../instrmem/v0.1/instr_memory.v
+I_GPR=-I../../gpr/v0.1 ../../gpr/v0.1/gpr_register.v
+I_ALUCONTROL=-I../../alu_control/v0.1 ../../alu_control/v0.1/alu_control.v
+I_ALU8=-I../../alu/v0.1 ../../alu/v0.1/alu.v
+I_DATAMEM=-I../../datamem/v0.1 ../../datamem/v0.1/data_memory.v
+
+make:
+ iverilog -g2005-sv -o data_path data_path.v $(I_INSTRMEM) $(I_GPR) $(I_ALUCONTROL) $(I_ALU8) $(I_DATAMEM)
+ iverilog -g2005-sv -o test_data_path data_path.v test_data_path.v $(I_INSTRMEM) $(I_GPR) $(I_ALUCONTROL) $(I_ALU8) $(I_DATAMEM)
+
+test:
+ ./test_data_path
+
+
+wave:
+ gtkwave test_data_path.vcd \ No newline at end of file
diff --git a/datapath/v0.1/data_path.v b/datapath/v0.1/data_path.v
new file mode 100644
index 0000000..aee5739
--- /dev/null
+++ b/datapath/v0.1/data_path.v
@@ -0,0 +1,129 @@
+module data_path(
+ input clk,
+ input jump,mem_read, mem_write, alu_src, reg_dst, mem_to_reg, reg_write, bne, beq,
+ input [1:0]alu_op,
+ output [3:0]opcode
+);
+
+reg [15:0]pc_current;
+wire [15:0]pc_next;
+wire [15:0]pc_2;
+wire [15:0]instr;
+wire [2:0]reg_write_dest;
+wire [15:0]reg_write_data;
+wire [2:0]reg_read_addr_1;
+wire [15:0]reg_read_data_1;
+wire [2:0]reg_read_addr_2;
+wire [15:0]reg_read_data_2;
+wire [15:0]ext_im;
+wire [15:0]read_data2;
+wire [2:0]alu_control;
+wire [15:0]alu_out;
+wire zero_flag;
+wire [15:0]pc_j;
+wire [15:0]pc_beq;
+wire [15:0]pc_beq2;
+wire [15:0]pc_bne;
+wire [15:0]pc_bne2;
+wire beq_control;
+wire bne_control;
+wire [12:0]jump_shift;
+wire [15:0]mem_read_data;
+
+//set start position counter to 0
+initial begin
+ pc_current <= 16'd0;
+end
+
+//on pos edge set poisition counter to next value
+always @(posedge clk)
+begin
+ pc_current <= pc_next;
+end
+
+//set value of next instruction position
+assign pc_2 = pc_current + 16'd2;
+
+//read current instruction from pc_current and write to instr
+instr_memory im(
+ .pc(pc_current),
+ .instruction(instr)
+);
+
+//jump shift 2
+assign jump_shift = {instr[11:0],1'b0};
+
+//register where to write data
+assign reg_write_dest = (reg_dst==1'b1) ? instr[5:3] : instr[8:6];
+
+//2 read register addresses
+assign reg_read_addr_1 = instr[11:9];
+assign reg_read_addr_2 = instr[8:6];
+
+
+//General purpose register,process values according to settings
+gpr_register gpr(
+ .clk(clk),
+ .reg_write_en(reg_write),
+ .reg_write_dest(reg_write_dest),
+ .reg_write_data(reg_write_data),
+ .reg_read_addr_1(reg_read_addr_1),
+ .reg_read_data_1(reg_read_data_1),
+ .reg_read_addr_2(reg_read_addr_2),
+ .reg_read_data_2(reg_read_data_2)
+);
+
+//imidiate extend, set all higher bits to value of the last bit
+assign ext_im = {{10{instr[5]}}, instr[5:0]};
+
+//alu control unit
+alu_control ac(
+ .alu_op(alu_op),
+ .opcode(instr[15:12]),
+ .alu_cnt(alu_control)
+);
+
+// multiplexer read from ext or from data register
+//read imidiate value or one from alu
+assign read_data2 = (alu_src==1'b1) ? ext_im : reg_read_data_2;
+
+alu alu(
+ .a(reg_read_data_1),
+ .b(read_data2),
+ .alu_sel(alu_control),
+ .alu_out(alu_out),
+ .carry_out(zero_flag)
+);
+
+//position counter values if
+assign pc_beq = pc_2 + {ext_im[14:0], 1'b0};
+assign pc_bne = pc_2 + {ext_im[14:0], 1'b0};
+
+assign beq_control = beq & zero_flag;
+assign bne_control = bne & (~zero_flag);
+
+//if beq then jump imidiate value, else jump +2 positions
+assign pc_beq2 = (beq_control == 1'b1) ? pc_beq : pc_2;
+//if bne jusm imidiate value, else jump beq value
+assign pc_bne2 = (bne_control == 1'b1) ? pc_bne : pc_beq2;
+
+assign pc_j = {pc_2[15:13],jump_shift};
+
+assign pc_next = (jump == 1'b1) ? pc_j : pc_bne2;
+
+data_memory dm(
+ .clk(clk),
+ .mem_access_addr(alu_out),
+ .mem_write_data(reg_read_data_2),
+ .mem_write_en(mem_write),
+ .mem_read(mem_read),
+ .mem_read_data(mem_read_data)
+);
+
+//writeback
+assign reg_write_data = (mem_to_reg == 1'b1)? mem_read_data : alu_out;
+
+assign opcode = instr[15:12];
+
+
+endmodule \ No newline at end of file
diff --git a/datapath/v0.1/test_data_path.v b/datapath/v0.1/test_data_path.v
new file mode 100644
index 0000000..9625087
--- /dev/null
+++ b/datapath/v0.1/test_data_path.v
@@ -0,0 +1,158 @@
+`timescale 1ns/1ps
+
+module test_data_path;
+
+reg clk;
+reg jump;
+reg mem_read;
+reg mem_write;
+reg alu_src;
+reg reg_dst;
+reg mem_to_reg;
+reg reg_write;
+reg bne;
+reg beq;
+reg [1:0]alu_op;
+reg [3:0]opcode;
+
+data_path uut(
+ .clk(clk),
+ .jump(jump),
+ .mem_read(mem_read),
+ .mem_write(mem_write),
+ .alu_src(alu_src),
+ .reg_dst(reg_dst),
+ .mem_to_reg(mem_to_reg),
+ .reg_write(reg_write),
+ .bne(bne),
+ .beq(beq),
+ .alu_op(alu_op),
+ .opcode(opcode)
+);
+
+initial begin
+ $display("Start testing data path");
+ $dumpfile("test_data_path.vcd");
+ $dumpvars(0,test_data_path);
+
+ clk=0;
+ jump=0;
+ mem_read=0;
+ mem_write=0;
+ alu_src=0;
+ reg_dst=0;
+ mem_to_reg=0;
+ reg_write=0;
+ bne=0;
+ beq=0;
+ alu_op=2'b00;
+
+
+ #10
+ clk=1;
+
+ #10
+ clk=0;
+
+ #10
+ clk=1;
+
+ #10
+ clk=0;
+
+ #10
+ clk=1;
+
+ #10
+ clk=0;
+
+ #10
+ clk=1;
+
+ #10
+ clk=0;
+
+ #10
+ clk=1;
+
+ #10
+ clk=0;
+
+ #10
+ clk=1;
+
+ #10
+ clk=0;
+
+ #10
+ clk=1;
+
+ #10
+ clk=0;
+
+ #10
+ clk=1;
+
+ #10
+ clk=0;
+
+ #10
+ clk=1;
+
+ #10
+ clk=0;
+
+ #10
+ clk=1;
+
+ #10
+ clk=0;
+
+ #10
+ clk=1;
+
+ #10
+ clk=0;
+
+ #10
+ clk=1;
+
+ #10
+ clk=0;
+
+ #10
+ clk=1;
+
+ #10
+ clk=0;
+
+ #10
+ clk=1;
+
+ #10
+ clk=0;
+
+ #10
+ clk=1;
+
+ #10
+ clk=0;
+
+ #10
+ clk=1;
+
+ #10
+ clk=0;
+
+ #10
+ clk=1;
+
+ #10
+ clk=0;
+end
+
+initial begin
+ $monitor("At time=%t",$time);
+end
+
+endmodule \ No newline at end of file