Min преди 6 години
ревизия
64de66976e
променени са 12 файла, в които са добавени 416 реда и са изтрити 0 реда
  1. 7 0
      .gitignore
  2. 30 0
      UCL_project_y3.qpf
  3. 86 0
      UCL_project_y3.qsf
  4. BIN
      UCL_project_y3.qws
  5. 39 0
      src/alu.sv
  6. 8 0
      src/blocks/sign_ext.sv
  7. 123 0
      src/cpu.sv
  8. 24 0
      src/instr_mem.sv
  9. 21 0
      src/instruction_mem.sv
  10. 11 0
      src/io_unit.sv
  11. 15 0
      src/memory.sv
  12. 52 0
      src/reg_file.sv

+ 7 - 0
.gitignore

@@ -0,0 +1,7 @@
+*.bak
+*.rpt
+.qsys_edit/
+db/
+output_files/
+incremental_db/
+simulation/

+ 30 - 0
UCL_project_y3.qpf

@@ -0,0 +1,30 @@
+# -------------------------------------------------------------------------- #
+#
+# Copyright (C) 2018  Intel Corporation. All rights reserved.
+# Your use of Intel Corporation's design tools, logic functions 
+# and other software and tools, and its AMPP partner logic 
+# functions, and any output files from any of the foregoing 
+# (including device programming or simulation files), and any 
+# associated documentation or information are expressly subject 
+# to the terms and conditions of the Intel Program License 
+# Subscription Agreement, the Intel Quartus Prime License Agreement,
+# the Intel FPGA IP License Agreement, or other applicable license
+# agreement, including, without limitation, that your use is for
+# the sole purpose of programming logic devices manufactured by
+# Intel and sold by Intel or its authorized distributors.  Please
+# refer to the applicable agreement for further details.
+#
+# -------------------------------------------------------------------------- #
+#
+# Quartus Prime
+# Version 18.1.0 Build 625 09/12/2018 SJ Lite Edition
+# Date created = 13:15:52  September 19, 2019
+#
+# -------------------------------------------------------------------------- #
+
+QUARTUS_VERSION = "18.1"
+DATE = "13:15:52  September 19, 2019"
+
+# Revisions
+
+PROJECT_REVISION = "UCL_project_y3"

+ 86 - 0
UCL_project_y3.qsf

@@ -0,0 +1,86 @@
+# -------------------------------------------------------------------------- #
+#
+# Copyright (C) 2018  Intel Corporation. All rights reserved.
+# Your use of Intel Corporation's design tools, logic functions 
+# and other software and tools, and its AMPP partner logic 
+# functions, and any output files from any of the foregoing 
+# (including device programming or simulation files), and any 
+# associated documentation or information are expressly subject 
+# to the terms and conditions of the Intel Program License 
+# Subscription Agreement, the Intel Quartus Prime License Agreement,
+# the Intel FPGA IP License Agreement, or other applicable license
+# agreement, including, without limitation, that your use is for
+# the sole purpose of programming logic devices manufactured by
+# Intel and sold by Intel or its authorized distributors.  Please
+# refer to the applicable agreement for further details.
+#
+# -------------------------------------------------------------------------- #
+#
+# Quartus Prime
+# Version 18.1.0 Build 625 09/12/2018 SJ Lite Edition
+# Date created = 13:15:52  September 19, 2019
+#
+# -------------------------------------------------------------------------- #
+#
+# Notes:
+#
+# 1) The default values for assignments are stored in the file:
+#		UCL_project_y3_assignment_defaults.qdf
+#    If this file doesn't exist, see file:
+#		assignment_defaults.qdf
+#
+# 2) Altera recommends that you do not modify this file. This
+#    file is updated automatically by the Quartus Prime software
+#    and any changes you make may be lost or overwritten.
+#
+# -------------------------------------------------------------------------- #
+
+
+set_global_assignment -name FAMILY "Cyclone IV E"
+set_global_assignment -name DEVICE EP4CE22F17C6
+set_global_assignment -name TOP_LEVEL_ENTITY reg_file
+set_global_assignment -name ORIGINAL_QUARTUS_VERSION 18.1.0
+set_global_assignment -name PROJECT_CREATION_TIME_DATE "13:15:52  SEPTEMBER 19, 2019"
+set_global_assignment -name LAST_QUARTUS_VERSION "18.1.0 Lite Edition"
+set_global_assignment -name PROJECT_OUTPUT_DIRECTORY output_files
+set_global_assignment -name MIN_CORE_JUNCTION_TEMP 0
+set_global_assignment -name MAX_CORE_JUNCTION_TEMP 85
+set_global_assignment -name DEVICE_FILTER_PACKAGE FBGA
+set_global_assignment -name ERROR_CHECK_FREQUENCY_DIVISOR 1
+set_global_assignment -name NOMINAL_CORE_SUPPLY_VOLTAGE 1.2V
+set_global_assignment -name EDA_SIMULATION_TOOL "ModelSim-Altera (SystemVerilog)"
+set_global_assignment -name EDA_TIME_SCALE "1 ps" -section_id eda_simulation
+set_global_assignment -name EDA_OUTPUT_DATA_FORMAT "SYSTEMVERILOG HDL" -section_id eda_simulation
+set_global_assignment -name POWER_PRESET_COOLING_SOLUTION "23 MM HEAT SINK WITH 200 LFPM AIRFLOW"
+set_global_assignment -name POWER_BOARD_THERMAL_MODEL "NONE (CONSERVATIVE)"
+set_location_assignment PIN_J15 -to keys[0]
+set_location_assignment PIN_E1 -to keys[1]
+set_location_assignment PIN_A15 -to leds[0]
+set_location_assignment PIN_A13 -to leds[1]
+set_location_assignment PIN_B13 -to leds[2]
+set_location_assignment PIN_A11 -to leds[3]
+set_location_assignment PIN_D1 -to leds[4]
+set_location_assignment PIN_F3 -to leds[5]
+set_location_assignment PIN_B1 -to leds[6]
+set_location_assignment PIN_L3 -to leds[7]
+set_location_assignment PIN_M1 -to switches[0]
+set_location_assignment PIN_T8 -to switches[1]
+set_location_assignment PIN_B9 -to switches[2]
+set_location_assignment PIN_M15 -to switches[3]
+set_global_assignment -name VERILOG_SHOW_LMF_MAPPING_MESSAGES OFF
+set_global_assignment -name SYSTEMVERILOG_FILE src/cpu.sv
+set_global_assignment -name SYSTEMVERILOG_FILE src/reg_file.sv
+set_global_assignment -name SYSTEMVERILOG_FILE src/instr_mem.sv
+set_global_assignment -name SYSTEMVERILOG_FILE src/alu.sv
+set_global_assignment -name SYSTEMVERILOG_FILE src/memory.sv
+set_global_assignment -name SYSTEMVERILOG_FILE src/io_unit.sv
+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_ENABLE_STATUS TEST_BENCH_MODE -section_id eda_simulation
+set_global_assignment -name EDA_NATIVELINK_SIMULATION_TEST_BENCH testbench_1 -section_id eda_simulation
+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_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top

BIN
UCL_project_y3.qws


+ 39 - 0
src/alu.sv

@@ -0,0 +1,39 @@
+package alu_pkg;
+
+	typedef enum logic [2:0] { 
+		ALU_ADD=3'b000,
+		ALU_SUB=3'b001,
+		ALU_AND=3'b010,
+		ALU_OR =3'b011,
+		ALU_SLT=3'b100,
+		ALU_NOT=3'b101,
+		ALU___0=3'b110,
+		ALU_NOP=3'b111
+	} e_alu_op;
+	
+endpackage
+
+module alu(op, srcA, srcB, result, zero);	
+	input  e_alu_op 	op;
+	input  word 		srcA;
+	input  word			srcB;
+	output word			result;
+	output logic		zero;
+	
+	
+	always_comb begin
+	case(op)
+		ALU_ADD: result = srcA + srcB;
+		ALU_SUB: result = srcA - srcB;
+		ALU_AND: result = srcA & srcB;
+		ALU_OR : result = srcA | srcB;
+//		ALU_SLT: result = srcA < srcB; // Not in use
+		ALU_NOT: result = ~srcB;
+		ALU_NOP: result = srcA;
+		default: result = '0;
+	endcase
+	
+	zero = result == '0;
+	end
+	
+endmodule

+ 8 - 0
src/blocks/sign_ext.sv

@@ -0,0 +1,8 @@
+
+module sign_ext(data_in, data_out);
+	parameter WORD=8, EXT=4;
+	input [WORD-1:0]data_in;
+	output logic [WORD-1:0]data_out;
+	
+	
+endmodule

+ 123 - 0
src/cpu.sv

@@ -0,0 +1,123 @@
+import alu_pkg::*;
+package cpu_pkg;	
+	
+	typedef enum logic [1:0] {
+		RegA = 2'b00,
+		RegB = 2'b01,
+		RegC = 2'b10,
+		RegD = 2'b11
+	} e_reg;
+	
+	typedef enum logic [3:0] { 
+		NOP =4'h0,	// No operation
+		ADD =4'h1,  // $rs = $rs + $rt
+		ADDI=4'h2,  // $rs = $rs + $imm
+		SUB =4'h3,  // $rs = $rs - $rt
+		AND =4'h4,  // $rs = $rs & $rt
+		OR  =4'h5,  // $rs = $rs | $rt
+		NOT =4'h6,  // $rs = ~$rt
+		LW  =4'h7,  // Load word from $rt to $rs
+		SW  =4'h8,  // Save word from $rt to $rs
+		WO  =4'h9,  // Write $rs to output
+		RO  =4'hA,  // Read output to $rs
+		COPY=4'hB,  // $rs = $rt
+		JEQ =4'hC,  // Jump to $imm if $rs == $rt
+		ZERO=4'hD,  // $rs = 0x00
+		__0 =4'hE,  //
+		__1 =4'hF   //
+		
+	} e_instr;
+	
+	typedef logic [7:0] word;
+	typedef logic [1:0] regAddr;
+	
+endpackage
+
+module cpu(clk, rst, in_data, out_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
+
+	
+	always_ff@(posedge clk, negedge rst) begin
+		if (!rst) pc <= '0;
+		else pc <= pcn;
+	end
+	
+	// ==================
+	// Instruction memory
+	// ==================
+	e_instr instr;			// Instruction
+	word    imm;			// Immidiate value
+	instr_mem #(8) IMEM(clk, pc, instr, imm);
+	
+	// =====================
+	// 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 #(8,4) 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
+	// =====================
+	logic 	mem_wr_en;
+	word		mem_rd_data;
+	memory #(8,256) 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 == 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   = regAddr'(instr[5:4]);  // It's always $rs
+	assign reg_rd_addr_1 = regAddr'(instr[5:4]);  // $rs
+	assign reg_rd_addr_2 = regAddr'(instr[7:6]);  // $rt
+	
+	always_comb begin
+	case(instr)
+		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
+	end
+	
+	assign mem_wr_en = instr == SW;
+	assign mem_to_reg = instr == LW;
+	assign pcn = (alu_zero && instr == JEQ) ? imm : pc + 1;
+	
+endmodule

+ 24 - 0
src/instr_mem.sv

@@ -0,0 +1,24 @@
+import cpu_pkg::*;
+
+module instr_mem(clk, addr, instr, imm);
+	parameter WORD=8, SIZE=2**WORD;
+	input clk;
+	input  word 	addr;
+	output word		imm;
+	output e_instr instr;
+	
+	logic [WORD-1:0] 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
+	end
+	
+	always_ff @(posedge clk) begin
+		instr <= e_instr'(rom[addr]);
+		imm <= rom[addr + 1];
+	end
+
+endmodule

+ 21 - 0
src/instruction_mem.sv

@@ -0,0 +1,21 @@
+module instruction_mem(addr, data);
+parameter WORD=8;
+input [WORD-1:0] addr;
+output logic [WORD-1:0] data;
+
+always_comb begin
+	case(addr)
+		0: data <= 8'b1000_0000;
+		1: data <= 8'b0100_0000;
+		2: data <= 8'b0010_0000;
+		3: data <= 8'b0001_0000;
+		4: data <= 8'b0000_1000;
+		5: data <= 8'b0000_0100;
+		6: data <= 8'b0000_0010;
+		7: data <= 8'b0000_0001;
+	-	8: data <= 8'hFF;
+		default: data = 0;
+	endcase
+end
+ 
+endmodule

+ 11 - 0
src/io_unit.sv

@@ -0,0 +1,11 @@
+
+module io_unit(switches, keys, leds);
+	input  logic [3:0]switches;
+	input  logic [1:0]keys;
+	output logic [7:0]leds;
+	
+	assign rst = keys[0];
+	assign clk = keys[1];
+	cpu CPU(clk, rst);
+	
+endmodule

+ 15 - 0
src/memory.sv

@@ -0,0 +1,15 @@
+module memory(clk, addr, rd_data, wr_data, wr_en);
+	parameter WORD=8, MEM_SIZE=2**WORD;
+	input clk, wr_en;
+	input [WORD-1:0]addr;
+	input [WORD-1:0]wr_data;
+	output logic [WORD-1:0]rd_data;
+	
+	logic [WORD-1:0]memory[MEM_SIZE-1:0];
+	
+	always_ff@(posedge clk) begin
+		if(wr_en) memory[addr] <= wr_data;
+		else rd_data <= memory[addr];
+	end
+	
+endmodule

+ 52 - 0
src/reg_file.sv

@@ -0,0 +1,52 @@
+module reg_file(clk, rd_addr1, rd_addr2, rd_data1, rd_data2, wr_addr, wr_data, wr_en);
+	parameter    WORD		  = 8;
+	parameter    REG_SIZE  = 4;
+	localparam   ADDR_SIZE = $clog2(REG_SIZE);
+	
+	input logic  clk, wr_en;
+	input 		 [ADDR_SIZE-1:0] rd_addr1;
+	input 		 [ADDR_SIZE-1:0] rd_addr2;
+	input 		 [ADDR_SIZE-1:0] wr_addr;
+	input 		 [WORD-1:0]		  wr_data;
+	output logic [WORD-1:0]      rd_data1;
+	output logic [WORD-1:0]      rd_data2;
+	
+	logic        [WORD-1:0]	registry [ADDR_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;
+	end
+	
+endmodule
+
+
+module reg_file_tb;
+	logic clk, wr_en;
+	logic [1:0]rd_addr1;
+	logic [1:0]rd_addr2;
+	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);
+	
+	initial begin
+		clk = 0;
+		forever #5ns clk = ~clk;
+	end
+	
+	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;
+		#5ns wr_en = 0;
+	end
+	
+endmodule
+