Ver código fonte

separate cpu modules WIP

Min 6 anos atrás
pai
commit
02b79c42f5

+ 10 - 3
UCL_project_y3.qsf

@@ -73,14 +73,21 @@ set_global_assignment -name EDA_NATIVELINK_SIMULATION_TEST_BENCH testbench_1 -se
 set_global_assignment -name EDA_TEST_BENCH_NAME testbench_1 -section_id eda_simulation
 set_global_assignment -name EDA_DESIGN_INSTANCE_NAME NA -section_id testbench_1
 set_global_assignment -name EDA_TEST_BENCH_MODULE_NAME testbench_1 -section_id testbench_1
-set_global_assignment -name EDA_TEST_BENCH_FILE src/reg_file.sv -section_id testbench_1
 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_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top
+set_global_assignment -name SYSTEMVERILOG_FILE src/datapath.sv
+set_global_assignment -name SYSTEMVERILOG_FILE src/blocks/instr_mem.sv
 set_global_assignment -name SYSTEMVERILOG_FILE src/cpu.sv
 set_global_assignment -name SYSTEMVERILOG_FILE src/blocks/reg_file.sv
 set_global_assignment -name SYSTEMVERILOG_FILE src/blocks/memory.sv
 set_global_assignment -name SYSTEMVERILOG_FILE src/blocks/alu.sv
 set_global_assignment -name SYSTEMVERILOG_FILE src/io_unit.sv
-set_global_assignment -name SYSTEMVERILOG_FILE src/general.sv
+set_global_assignment -name SYSTEMVERILOG_FILE src/general.sv
+set_global_assignment -name SYSTEMVERILOG_FILE src/controller.sv
+set_global_assignment -name EDA_TEST_BENCH_FILE src/blocks/reg_file_tb.sv -section_id testbench_1
+set_global_assignment -name EDA_TEST_BENCH_FILE src/blocks/memory.sv -section_id testbench_1
+set_global_assignment -name EDA_TEST_BENCH_FILE src/blocks/alu.sv -section_id testbench_1
+set_global_assignment -name EDA_TEST_BENCH_FILE src/controller.sv -section_id testbench_1
+set_global_assignment -name EDA_TEST_BENCH_FILE src/datapath.sv -section_id testbench_1
+set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top

+ 42 - 4
src/blocks/alu.sv

@@ -14,13 +14,51 @@ module alu(op, srcA, srcB, result, zero);
 		ALU_SUB: result = srcA - srcB;
 		ALU_AND: result = srcA & srcB;
 		ALU_OR : result = srcA | srcB;
-//		ALU_SLT: result = srcA < srcB; // Not in use
+		ALU_SLT: result = srcA > srcB;
 		ALU_NOT: result = ~srcB;
 		ALU_NOP: result = srcA;
-		default: result = '0;
+		default: result = 0;
 	endcase
-	
-	zero = result == '0;
 	end
+	assign zero = result == 0;
+	
+endmodule
+
+module alu_tb;
+	e_alu_op op;
+	word srcA, srcB, result;
+	logic zero;
 	
+	alu ALU(op, srcA, srcB, result, zero);
+	
+	initial begin
+		op = ALU_NOP;
+		srcA = 120;
+		srcB = 100;
+		#5ns;
+		assert(result == srcA);
+		op = ALU_ADD;
+		#5ns;
+		assert(result == 220);
+		op = ALU_SUB;
+		#5ns;
+		assert(result == 20);
+		op = ALU_AND;
+		// 01100100 & 01111000 = 01100000
+		#5ns;
+		assert(result == 96);
+		op = ALU_OR;
+		// 01100100 | 01111000 = 01111100
+		#5ns;
+		assert(result == 124);
+		op = ALU_SLT;
+		#5ns;
+		assert(result == 1);
+		srcB = 140;
+		#5ns;
+		assert(result == 0);
+		assert(zero == 1);
+		$stop;
+	end
+
 endmodule

+ 1 - 2
src/blocks/instr_mem.sv

@@ -1,4 +1,3 @@
-//import cpu_pkg::*;
 import project_pkg::*;
 
 module instr_mem(addr, instr, imm);
@@ -6,7 +5,7 @@ module instr_mem(addr, instr, imm);
 	output word	imm;
 	output word	instr;
 	
-	logic [word_length-1:0] rom [rom_length-1:0];
+	logic [word_size-1:0] rom [rom_size-1:0];
 	
 	always_comb begin
 		rom[0] = {NOP, RegA, RegA};  // Do nothing

+ 32 - 3
src/blocks/memory.sv

@@ -7,10 +7,39 @@ module memory(clk, addr, rd_data, wr_data, wr_en);
 	output word rd_data;
 	
 	logic [word_size-1:0]memory[mem_size-1:0];
+	assign rd_data = memory[addr];
 	
-	always_ff@(posedge clk) begin
-		if(wr_en) memory[addr] <= wr_data;
-		else rd_data <= memory[addr];
+	always_ff@(posedge clk) if(wr_en) memory[addr] <= wr_data;
+	
+	
+endmodule
+
+module memory_tb;
+	logic clk, wr_en;
+	word addr, wr_data, rd_data;
+	
+	initial begin
+		clk = 0;
+		forever #5ns clk = ~clk;
 	end
 	
+	initial begin
+		addr = 0;
+		wr_en = 1;
+		for(int i=0;i<mem_size;i++) begin
+			wr_data = i;
+			addr = i;
+			#10ns;
+		end
+		wr_en = 0;
+		wr_data = 0;
+		for(int i=0;i<mem_size;i++) begin
+			#10ns;
+			addr = i;
+			assert(rd_data == i);
+		end
+		$stop;
+	end
+
 endmodule
+

+ 47 - 19
src/blocks/reg_file.sv

@@ -1,32 +1,36 @@
-module reg_file(clk, rd_addr1, rd_addr2, rd_data1, rd_data2, wr_addr, wr_data, wr_en);
-	input logic  clk, wr_en;
-	input regAddr 	rd_addr1;
-	input regAddr 	rd_addr2;
-	input regAddr 	wr_addr;
-	input regAddr 	wr_data;
+import project_pkg::*;
+
+module reg_file(clk, rst, rd_addr1, rd_addr2, rd_data1, rd_data2, wr_addr, wr_data, wr_en);
+	input logic  clk, rst, wr_en;
+	input  regAddr rd_addr1;
+	input  regAddr rd_addr2;
+	input  regAddr	wr_addr;
+	input  word		wr_data;
 	output word 	rd_data1;
 	output word 	rd_data2;
 	
 	logic [word_size-1:0] registry [reg_size-1:0];
 	
 	always_ff@(posedge clk) begin
-		rd_data1 <= registry[rd_addr1];
-		rd_data2 <= registry[rd_addr2];
-		if(wr_en) registry[wr_addr] <= wr_data;
+	  	if(rst) for(int i=0;i<reg_size;i++) registry[i] <= '0;
+		else if(wr_en) registry[wr_addr] <= wr_data;
 	end
 	
+	assign rd_data1 = registry[rd_addr1];
+	assign rd_data2 = registry[rd_addr2];
+	
 endmodule
 
 module reg_file_tb;
-	logic clk, wr_en;
+	logic clk, rst, wr_en;
 	logic [1:0]rd_addr1;
 	logic [1:0]rd_addr2;
+	logic [1:0]wr_addr;
 	logic [7:0]rd_data1;
 	logic [7:0]rd_data2;
-	logic [1:0]wr_addr;
 	logic [7:0]wr_data;
 	
-	reg_file test_reg_file(clk, rd_addr1, rd_addr2, rd_data1, rd_data2, wr_addr, wr_data, wr_en);
+	reg_file test_reg_file(clk, rst, rd_addr1, rd_addr2, rd_data1, rd_data2, wr_addr, wr_data, wr_en);
 	
 	initial begin
 		clk = 0;
@@ -35,13 +39,37 @@ module reg_file_tb;
 	
 	initial begin
 		rd_addr1 = 2'b00;
-		rd_addr2 = 2'b01;
-		wr_addr	= 2'b00;
-		wr_en 	= 0;
-		wr_data	= 8'hFF;
-		#10ns wr_en = 1;
-		#10ns wr_addr =  2'b01;
-		#10ns wr_en = 0;
+		rd_addr2 = 2'b00;
+		wr_addr	= 0;
+		rst = 1;
+		wr_en = 1;
+		wr_data = 8'hAA;
+		#10ns 
+		rst=0;
+		wr_data = 8'hBB;
+		wr_addr = 1;
+		#10ns
+		wr_data = 8'hCC;
+		wr_addr = 2;
+		#10ns
+		wr_data = 8'hDD;
+		wr_addr = 3;
+		#10ns
+		wr_en = 0;
+		wr_data = 0;
+		rd_addr1 = 3;
+		rd_addr2 = 0;
+		#10ns
+		assert(rd_data1==8'hDD);
+		assert(rd_data2==8'hAA);
+		rd_addr1 = 2;
+		rd_addr2 = 1;
+		#10ns
+		assert(rd_data1==8'hCC);
+		assert(rd_data2==8'hBB);
+		$stop;
 	end
 	
 endmodule
+
+

+ 0 - 0
src/blocks/reg_file_tb.sv


+ 196 - 0
src/controller.sv

@@ -0,0 +1,196 @@
+import project_pkg::*;
+
+module controller(instr, zero, alu_op, mem_wr, reg_wr, pc_src, alu_src, mem_to_reg, instr_op, rs, rt);
+	input word instr;
+	input logic zero; // That's from ALU for J instructions
+	output e_alu_op alu_op;
+	output logic mem_wr, reg_wr, alu_src, mem_to_reg, pc_src;
+	output e_instr instr_op;
+	output regAddr rs, rt;
+	// Instruction decoding
+	assign instr_op 	= e_instr'(instr[7:4]);
+	assign rs 			= regAddr'(instr[3:2]);
+	assign rt 			= regAddr'(instr[1:0]);
+
+	always_comb begin
+	case(instr_op)
+			NOP : begin
+					alu_op = ALU_NOP;
+					reg_wr = 0;
+			end
+			ADD : begin
+					alu_op = ALU_ADD;
+					reg_wr = 1;
+			end
+			ADDI: begin
+					alu_op = ALU_ADD;
+					reg_wr = 1;
+			end
+			SUB : begin
+1					alu_op = ALU_SUB;
+					reg_wr = 1;
+			end
+			AND : begin
+					alu_op = ALU_AND;
+					reg_wr = 1;
+			end
+			OR  : begin
+					alu_op = ALU_OR;
+					reg_wr = 1;
+			end
+			NOT : begin
+					alu_op = ALU_NOT;
+					reg_wr = 1;
+			end
+			LW  : begin
+					alu_op = ALU_NOP;
+					reg_wr = 0;
+			end
+			SW  : begin
+					alu_op = ALU_NOP;
+					reg_wr = 0;
+			end
+			WO  : begin
+					alu_op = ALU_NOP;
+					reg_wr = 0;
+			end
+			RO  : begin
+					alu_op = ALU_NOP;
+					reg_wr = 1;
+			end
+			COPY: begin
+					alu_op = ALU_NOP;
+					reg_wr = 1;
+			end
+			JEQ : begin
+					alu_op = ALU_SUB;
+					reg_wr = 0;
+			end
+			ZERO: begin
+					alu_op = ALU_NOP;
+					reg_wr = 0;
+			end
+			default: begin
+					alu_op = ALU_NOP;
+					reg_wr = 0;
+			end
+	endcase
+	end
+	
+	assign mem_wr = instr_op == SW;
+	assign mem_to_reg = instr_op == LW;
+	assign pc_src = zero && instr_op == JEQ;
+	assign alu_src = instr_op == ADDI;	
+
+endmodule
+
+module controller_tb;
+	word instr;
+	logic zero, mem_wr, reg_wr, alu_src, mem_to_reg, pc_src;
+	e_alu_op alu_op;
+
+	controller CTR(instr, zero, alu_op, mem_wr, reg_wr, pc_src, alu_src, mem_to_reg);
+
+	initial begin
+		instr = 8'h00;
+		zero = 1;
+		#5ns;
+		assert(alu_op == ALU_NOP);
+		assert(mem_wr == 0);
+		assert(reg_wr == 0);
+		assert(pc_src == 0);
+		assert(alu_src == 0);
+		assert(mem_to_reg == 0);
+		instr = 8'h10;
+		#5ns;
+		assert(alu_op == ALU_ADD);
+		assert(mem_wr == 0);
+		assert(reg_wr == 1);
+		assert(pc_src == 0);
+		assert(alu_src == 0);
+		assert(mem_to_reg == 0);
+		instr = 8'h20;
+		#5ns;
+		assert(alu_op == ALU_ADD);
+		assert(mem_wr == 0);
+		assert(reg_wr == 1);
+		assert(pc_src == 0);
+		assert(alu_src == 1);
+		assert(mem_to_reg == 0);
+		instr = 8'h30;
+		#5ns;
+		assert(alu_op == ALU_SUB);
+		assert(mem_wr == 0);
+		assert(reg_wr == 1);
+		assert(pc_src == 0);
+		assert(alu_src == 0);
+		assert(mem_to_reg == 0);
+		instr = 8'h40;
+		#5ns;
+		assert(alu_op == ALU_AND);
+		assert(mem_wr == 0);
+		assert(reg_wr == 1);
+		assert(pc_src == 0);
+		assert(alu_src == 0);
+		assert(mem_to_reg == 0);
+		instr = 8'h50;
+		#5ns;
+		assert(alu_op == ALU_OR);
+		assert(mem_wr == 0);
+		assert(reg_wr == 1);
+		assert(pc_src == 0);
+		assert(alu_src == 0);
+		assert(mem_to_reg == 0);
+		instr = 8'h60;
+		#5ns;
+		assert(alu_op == ALU_NOT);
+		assert(mem_wr == 0);
+		assert(reg_wr == 1);
+		assert(pc_src == 0);
+		assert(alu_src == 0);
+		assert(mem_to_reg == 0);
+		instr = 8'h70;
+		#5ns;
+		assert(alu_op == ALU_NOP);
+		assert(mem_wr == 0);
+		assert(reg_wr == 1);
+		assert(pc_src == 0);
+		assert(alu_src == 0);
+		assert(mem_to_reg == 1);
+		instr = 8'h80;
+		#5ns;
+		assert(alu_op == ALU_NOP);
+		assert(mem_wr == 1);
+		assert(reg_wr == 0);
+		assert(pc_src == 0);
+		assert(alu_src == 0);
+		assert(mem_to_reg == 0);
+		instr = 8'hB0;
+		#5ns;
+		assert(alu_op == ALU_NOP);
+		assert(mem_wr == 0);
+		assert(reg_wr == 1);
+		assert(pc_src == 0);
+		assert(alu_src == 0);
+		assert(mem_to_reg == 0);
+		instr = 8'hC0;
+		#5ns;
+		assert(alu_op == ALU_SUB);
+		assert(mem_wr == 0);
+		assert(reg_wr == 0);
+		assert(pc_src == 1);
+		assert(alu_src == 0);
+		assert(mem_to_reg == 0);
+		zero = 0;
+		#5ns;
+		assert(alu_op == ALU_SUB);
+		assert(mem_wr == 0);
+		assert(reg_wr == 0);
+		assert(pc_src == 0);
+		assert(alu_src == 0);
+		assert(mem_to_reg == 0);
+
+		$stop;
+	end
+endmodule
+

+ 9 - 12
src/cpu.sv

@@ -23,11 +23,11 @@ module cpu(clk, rst, in_data, out_data);
 	e_instr instr_op;
 	regAddr rs, rt;
 	
-	instr_mem #(8) IMEM(clk, pc, instr, imm);
+	instr_mem IMEM(pc, instr, imm);
 	// Instruction decoding
-	assign instr_op 	= instr[7:4];
-	assign rs 			= instr[3:2];
-	assign rt 			= instr[1:0];
+	assign instr_op 	= e_instr'(instr[7:4]);
+	assign rs 			= regAddr'(instr[3:2]);
+	assign rt 			= regAddr'(instr[1:0]);
 	
 	// =====================
 	// ALU
@@ -49,7 +49,7 @@ module cpu(clk, rst, in_data, out_data);
 	regAddr	reg_rd_addr_2;
 	word		reg_rd_data_1;
 	word		reg_rd_data_2;
-	reg_file #(8,2) RFILE(clk, reg_rd_addr_1, reg_rd_addr_2, reg_rd_data_1, reg_rd_data_2, reg_wr_addr, reg_wr_data, reg_wr_en);
+	reg_file RFILE(clk, reg_rd_addr_1, reg_rd_addr_2, reg_rd_data_1, reg_rd_data_2, reg_wr_addr, reg_wr_data, reg_wr_en);
 	
 	// =====================
 	// System memory
@@ -75,7 +75,7 @@ module cpu(clk, rst, in_data, out_data);
 	assign reg_rd_addr_2 = rt;
 	
 	always_comb begin
-	case(instr)
+	case(instr_op)
 		ADD:  	alu_op = ALU_ADD;
 		ADDI: 	alu_op = ALU_ADD;
 		SUB:  	alu_op = ALU_SUB;
@@ -87,12 +87,9 @@ module cpu(clk, rst, in_data, out_data);
 	endcase
 	end
 	
-	assign mem_wr_en = instr == SW;
-	assign mem_to_reg = instr == LW;
-	assign pcn = (alu_zero && instr == JEQ) ? imm : pc + 1;
+	assign mem_wr_en = instr_op == SW;
+	assign mem_to_reg = instr_op == LW;
+	assign pcn = (alu_zero && instr_op == JEQ) ? imm : pc + 1;
 	
 endmodule
 
-module cpu_tb;
-
-endmodule

+ 79 - 0
src/datapath.sv

@@ -0,0 +1,79 @@
+import project_pkg::*;
+
+module datapath(clk, rst, rs, rt, imm, alu_op, reg_wr, pc_src, alu_src, mem_to_reg, pc, alu_out, mem_data, alu_zero);
+	input logic clk, rst, reg_wr, pc_src, alu_src, mem_to_reg;
+	input e_reg rs, rt;
+	input e_alu_op alu_op;
+	input word imm, mem_data;
+	output word pc, alu_out;
+	output logic alu_zero;
+	
+	// Reg File
+	word reg_rd_d1, reg_rd_d2, reg_wr_d;
+	e_reg reg_rd_a1, reg_rd_a2, reg_wr_a;
+	assign reg_rd_a1 = rs;
+	assign reg_rd_a2 = rt;
+	assign reg_wr_a = rs;
+	assign reg_wr_d = (mem_to_reg) ? mem_data : alu_out; 
+	reg_file RFILE(clk, rst, reg_rd_a1, reg_rd_a2, reg_rd_d1, reg_rd_d2, reg_wr_a, reg_wr_d, reg_wr);
+
+	// ALU
+	word alu_srcA, alu_srcB;
+	assign alu_srcA = reg_rd_d1;
+	assign alu_srcB = (alu_src) ? reg_rd_d2 : imm;
+	alu ALU(alu_op, alu_srcA, alu_srcB, alu_out, alu_zero);
+	
+	// Program counter
+	word pcn; 	// PC next
+	assign pcn = (pc_src) ? imm : pc + 1;
+	always_ff@(posedge clk, negedge rst) begin
+	  	if (rst) pc <= 0;
+		else pc <= pcn;
+	end
+endmodule
+
+module datapath_tb;
+	logic clk, rst, reg_wr, pc_src, alu_src, mem_to_reg, alu_zero;
+	e_reg rs, rt;
+	e_alu_op alu_op;
+	word imm, mem_data, pc, alu_out;
+	datapath DPATH(clk, rst, rs, rt, imm, alu_op, reg_wr, pc_src, alu_src, mem_to_reg, pc, alu_out, mem_data, alu_zero);
+
+	initial begin
+		clk = 0;
+		forever #5ns clk = ~clk;
+	end
+
+	initial begin
+		rst = 1;
+		reg_wr = 0;
+		pc_src = 0;
+		alu_src = 0;
+		mem_to_reg = 0;
+		rs = RegA;
+		rt = RegA;
+		alu_op = ALU_NOP;
+		imm = 8'h00;
+		mem_data = 8'h00;
+		#10ns;
+		rst = 0;
+		reg_wr = 1;
+		mem_to_reg = 1;
+		mem_data = 8'h7A;
+		#10ns;
+		rs = RegB;
+		mem_data = 8'h8A;
+		#10ns;
+		rs = RegC;
+		mem_data = 8'h9A;
+		#10ns;
+		rs = RegD;
+		mem_data = 8'hFD;
+		#10ns;
+		rs = RegA;
+		#10ns;
+		$stop;
+	end
+
+
+endmodule

+ 1 - 1
src/io_unit.sv

@@ -6,6 +6,6 @@ module io_unit(switches, keys, leds);
 	
 	assign rst = keys[0];
 	assign clk = keys[1];
-//	cpu CPU(clk, rst);
+	cpu CPU(clk, rst);
 	
 endmodule