Selaa lähdekoodia

Working prototype

Min 6 vuotta sitten
vanhempi
commit
880b1f42e9
7 muutettua tiedostoa jossa 106 lisäystä ja 111 poistoa
  1. 7 5
      UCL_project_y3.qsf
  2. 39 0
      memory/rom_test.mem
  3. 11 7
      src/blocks/instr_mem.sv
  4. 1 3
      src/blocks/reg_file.sv
  5. 4 4
      src/controller.sv
  6. 32 86
      src/cpu.sv
  7. 12 6
      src/datapath.sv

+ 7 - 5
UCL_project_y3.qsf

@@ -76,6 +76,13 @@ set_global_assignment -name EDA_TEST_BENCH_MODULE_NAME testbench_1 -section_id t
 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 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_global_assignment -name EDA_TEST_BENCH_FILE src/cpu.sv -section_id testbench_1
+set_global_assignment -name MIF_FILE memory/rom_test.mem
 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
@@ -85,9 +92,4 @@ 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/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

+ 39 - 0
memory/rom_test.mem

@@ -0,0 +1,39 @@
+00 // NOP
+20 // ADDI regA = FA
+FA // imm
+24 // ADDI regB = 01
+01 // imm
+31 // SUB regA = regA - regB
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+

+ 11 - 7
src/blocks/instr_mem.sv

@@ -1,19 +1,23 @@
 import project_pkg::*;
 
 module instr_mem(addr, instr, imm);
+	parameter IMEM_FILE = "";
 	input  word addr;
 	output word	imm;
 	output word	instr;
 	
 	logic [word_size-1:0] rom [rom_size-1:0];
-	
-	always_comb begin
-		rom[0] = {NOP, RegA, RegA};  // Do nothing
-		rom[1] = {ADDI, RegA, RegA}; // Set $ra = 0xFF
-		rom[2] = 8'hFF;
-		rom[3] = {WO, RegA, RegA};   // Show $ra
+	initial $readmemh(IMEM_FILE, rom);
+	initial begin
+		 $display("Instruction ROM dump");
+		 for (int i=0; i < rom_size; i+=16) begin
+			$write("%h:", i);
+			for(int j=0; j<16 && j+i < rom_size; j++)
+		 		$write(" %h", rom[i+j]);
+			$display(" :%h", i);
+		end
 	end
-	
+ 
 	always_comb begin
 		instr = rom[addr];
 		imm = rom[addr + 1];

+ 1 - 3
src/blocks/reg_file.sv

@@ -2,9 +2,7 @@ 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  e_reg rd_addr1, rd_addr2, wr_addr;
 	input  word		wr_data;
 	output word 	rd_data1;
 	output word 	rd_data2;

+ 4 - 4
src/controller.sv

@@ -6,11 +6,11 @@ module controller(instr, zero, alu_op, mem_wr, reg_wr, pc_src, alu_src, mem_to_r
 	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;
+	output e_reg rs, rt;
 	// Instruction decoding
 	assign instr_op 	= e_instr'(instr[7:4]);
-	assign rs 			= regAddr'(instr[3:2]);
-	assign rt 			= regAddr'(instr[1:0]);
+	assign rs 			= e_reg'(instr[3:2]);
+	assign rt 			= e_reg'(instr[1:0]);
 
 	always_comb begin
 	case(instr_op)
@@ -27,7 +27,7 @@ module controller(instr, zero, alu_op, mem_wr, reg_wr, pc_src, alu_src, mem_to_r
 					reg_wr = 1;
 			end
 			SUB : begin
-1					alu_op = ALU_SUB;
+					alu_op = ALU_SUB;
 					reg_wr = 1;
 			end
 			AND : begin

+ 32 - 86
src/cpu.sv

@@ -1,95 +1,41 @@
 import project_pkg::*;
 
-module cpu(clk, rst, in_data, out_data);
+module cpu(clk, rst, instr, imm, pc, mem_addr, mem_wr_en, mem_wr_data, mem_rd_data);
 	input logic clk, rst;
-	input logic  [7:0]in_data;
-	output logic [7:0]out_data;
-	
-	// ==================
-	// Program counter
-	// ==================
-	word  pc;			// Program counter
-	word  pcn; 			// Next PC
+	input word instr, imm, mem_rd_data;
+	output logic mem_wr_en;
+	output word pc, mem_addr, mem_wr_data;
 
-	always_ff@(posedge clk, negedge rst) begin
-		if (!rst) pc <= '0;
-		else pc <= pcn;
-	end
-	
-	// ==================
-	// Instruction memory
-	// ==================
-	word	instr, imm;
+	// Controller
+	logic alu_zero, pc_src, reg_wr, alu_src, mem_to_reg;
 	e_instr instr_op;
-	regAddr rs, rt;
-	
-	instr_mem IMEM(pc, instr, imm);
-	// Instruction decoding
-	assign instr_op 	= e_instr'(instr[7:4]);
-	assign rs 			= regAddr'(instr[3:2]);
-	assign rt 			= regAddr'(instr[1:0]);
+	e_reg rs, rt;
+	e_alu_op alu_op;
 	
-	// =====================
-	// ALU
-	// =====================
-	e_alu_op	alu_op;
-	word		alu_result;
-	word		alu_srcA;
-	word		alu_srcB;
-	logic		alu_zero;
-	alu ALU(alu_op, alu_srcA, alu_srcB, alu_result, alu_zero);
-	
-	// =====================
-	// Register File
-	// =====================
-	logic		reg_wr_en;
-	regAddr	reg_wr_addr;
-	word		reg_wr_data;
-	regAddr	reg_rd_addr_1;
-	regAddr	reg_rd_addr_2;
-	word		reg_rd_data_1;
-	word		reg_rd_data_2;
-	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);
-	
-	// =====================
+	controller CTRL(instr, alu_zero, alu_op, mem_wr_en, reg_wr, pc_src, alu_src, mem_to_reg, instr_op, rs, rt);
+
+	// Datapath
+	datapath DPATH(clk, rst, rs, rt, imm, alu_op, reg_wr, pc_src, alu_src, mem_to_reg, pc, mem_addr, mem_rd_data, alu_zero, mem_wr_data);	
+endmodule
+
+module cpu_tb;
+	logic clk, rst, mem_wr; 
+	word pc, instr, imm, mem_addr, mem_data, mem_rd_data;	
+	cpu CPU(clk, rst, instr, imm, pc, mem_addr, mem_wr, mem_data, mem_rd_data);
+	// Instruction memory
+	instr_mem #("/home/min/devel/fpga/ucl_project_y3/memory/rom_test.mem") IMEM(pc, instr, imm);
 	// System memory
-	// =====================
-	logic 	mem_wr_en;
-	word		mem_rd_data;
-	memory RAM(clk, alu_result, mem_rd_data, reg_rd_data_2, mem_wr_en);
-	
-	// =====================
-	// Control unit
-	// =====================
-	logic reg_dst;
-	logic alu_src;
-	logic mem_to_reg;
-	
-	assign alu_srcA 	 = reg_rd_data_1;
-	assign alu_src     = (instr_op == ADDI);
-	assign alu_srcB    = (alu_src)    ? reg_rd_data_2 : imm;
-	assign reg_wr_data = (mem_to_reg) ? mem_rd_data   : alu_result;
-	
-	assign reg_wr_addr   = rs;
-	assign reg_rd_addr_1 = rs;
-	assign reg_rd_addr_2 = rt;
-	
-	always_comb begin
-	case(instr_op)
-		ADD:  	alu_op = ALU_ADD;
-		ADDI: 	alu_op = ALU_ADD;
-		SUB:  	alu_op = ALU_SUB;
-		AND:  	alu_op = ALU_AND;
-		OR:   	alu_op = ALU_OR;
-		NOT:  	alu_op = ALU_NOT;
-		JEQ:  	alu_op = ALU_SUB;
-		default: alu_op = ALU_NOP;
-	endcase
+	memory RAM(clk, mem_addr, mem_data, mem_rd_data, mem_wr);	
+	initial begin
+		clk = 0;
+		forever #5ns clk = ~clk;
 	end
-	
-	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
 
+	initial begin
+		rst = 1;
+		#10ns;
+		rst = 0;
+		#100ns;
+		$stop;
+	end
+endmodule

+ 12 - 6
src/datapath.sv

@@ -1,11 +1,11 @@
 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);
+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, mem_wr_data);
 	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 word pc, alu_out, mem_wr_data;
 	output logic alu_zero;
 	
 	// Reg File
@@ -14,19 +14,25 @@ module datapath(clk, rst, rs, rt, imm, alu_op, reg_wr, pc_src, alu_src, mem_to_r
 	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; 
+	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);
 
+	// Mem output data
+	assign mem_wr_data = reg_rd_a2;
+
 	// ALU
 	word alu_srcA, alu_srcB;
 	assign alu_srcA = reg_rd_d1;
-	assign alu_srcB = (alu_src) ? reg_rd_d2 : imm;
+	assign alu_srcB = (alu_src) ? imm : reg_rd_d2;
 	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
+	word pcj;   // PC jump, +2 if imm used otherwise +1
+	assign pcj = (alu_src) ? pc + 2 : pc + 1;
+	//assign pcj = pc + 1;
+	assign pcn = (pc_src) ? imm : pcj;
+	always_ff@(posedge clk) begin
 	  	if (rst) pc <= 0;
 		else pc <= pcn;
 	end