From 41f95d207760f2f06db925c31edd7a8ee52aa0bc Mon Sep 17 00:00:00 2001
From: GabrielTofvesson <gabriel.tofvesson@gmail.com>
Date: Mon, 15 Oct 2018 09:21:03 +0200
Subject: [PATCH] Added shift/rotate operations to ALU Added callback/timeout
 module Added pixel location output to VGA module Fixed state management for
 RAM module Lowered clock speed for circuit to 200MHz because 400MHz was
 unstable. NOTE: even 200MHz is quite unstable

---
 ALU.v          | 323 ++++++++++++++++++++++++++++++-------------------
 Callback.v     |  24 ++++
 RAM.v          |  21 ++--
 SevenSegment.v |  48 ++++++--
 VGA.v          |   4 +
 5 files changed, 276 insertions(+), 144 deletions(-)
 create mode 100644 Callback.v

diff --git a/ALU.v b/ALU.v
index f78a2aa..d3d0abb 100644
--- a/ALU.v
+++ b/ALU.v
@@ -1,9 +1,9 @@
 module ALU(
-	input wire [7:0] a,
-	input wire [7:0] b,
-	input wire [7:0] op,
-	output wire [7:0] z,
-	output wire [7:0] o_flags
+   input wire [7:0] a,
+   input wire [7:0] b,
+   input wire [7:0] op,
+   output wire [7:0] z,
+   output wire [7:0] o_flags
 );
 
 /*
@@ -23,136 +23,207 @@ H: N/A
 */
 
 reg [15:0] i_z;
-reg [7:0] i_flg;
+reg [7:0]  i_flg;
+reg        shift_rotate;
 
 wire [8:0] add_out;
+wire [7:0] lshift[0:2];
+wire       lshift_overflow[0:2];
+wire [7:0] rshift[0:2];
+wire       rshift_underflow[0:2];
 
 assign z = i_z[7:0];
 assign o_flags = i_flg;
 
 FastAdder8 fa8(.cin(), .a(a), .b(b), .out(add_out[7:0]), .cout(add_out[8]));
 
+// Left shift decoder
+LeftBitShifter #(.bits(8), .shiftby(1)) (a, b[0], shift_rotate, lshift[0], lshift_overflow[0]);
+LeftBitShifter #(.bits(8), .shiftby(2)) (lshift[0], b[1], shift_rotate, lshift[1], lshift_overflow[1]);
+LeftBitShifter #(.bits(8), .shiftby(4)) (lshift[1], b[2], shift_rotate, lshift[2], lshift_overflow[2]);
+//LeftBitShifter #(.bits(8), .shiftby(8)) (lshift[2], b[3], lshift[3], lshift_overflow[3]);
+//LeftBitShifter #(.bits(8), .shiftby(16)) (lshift[3], b[4], lshift[4], lshift_overflow[4]);
+//LeftBitShifter #(.bits(8), .shiftby(32)) (lshift[4], b[5], lshift[5], lshift_overflow[5]);
+//LeftBitShifter #(.bits(8), .shiftby(64)) (lshift[5], b[6], lshift[6], lshift_overflow[6]);
+//LeftBitShifter #(.bits(8), .shiftby(128)) (lshift[6], b[7], lshift[7], lshift_overflow[7]);
+
+// Right shift decoder
+RightBitShifter #(.bits(8), .shiftby(1)) (a, b[0], shift_rotate, rshift[0], rshift_underflow[0]);
+RightBitShifter #(.bits(8), .shiftby(2)) (rshift[0], b[1], shift_rotate, rshift[1], rshift_underflow[1]);
+RightBitShifter #(.bits(8), .shiftby(4)) (rshift[1], b[2], shift_rotate, rshift[2], rshift_underflow[2]);
+//RightBitShifter #(.bits(8), .shiftby(8)) (rshift[2], b[3], rshift[3], rshift_underflow[3]);
+//RightBitShifter #(.bits(8), .shiftby(16)) (rshift[3], b[4], rshift[4], rshift_underflow[4]);
+//RightBitShifter #(.bits(8), .shiftby(32)) (rshift[4], b[5], rshift[5], rshift_underflow[5]);
+//RightBitShifter #(.bits(8), .shiftby(64)) (rshift[5], b[6], rshift[6], rshift_underflow[6]);
+//RightBitShifter #(.bits(8), .shiftby(128)) (rshift[6], b[7], rshift[7], rshift_underflow[7]);
+
 always @* begin
-	case(op & 8'b00011111) // 5-bit instructions: 3 flag bits
-		// ADD
-		0: begin
-			i_z <= add_out;
-			i_flg <= add_out[8] ? 8'b1 : 8'b0; // Set overflow flag if necessary
-		end
-		
-		// SUB
-		1: begin
-			i_z <= a-b;
-			i_flg <= i_z[15] << 1;
-		end
-		
-		// MUL
-		2: begin
-			i_z <= a*b;
-			i_flg <= i_z[15:8] != 8'b0 ? 8'b1 : 8'b0;
-		end
-		
-		// DIV
-		3: begin
-			if(b != 8'b0) begin
-				i_z <= a/b;
-				i_flg <= 8'b0;
-			end else begin
-				i_z <= 16'b0;
-				i_flg <= 8'b10000;
-			end
-		end
-		
-		// CMP
-		4: begin
-			/*
-			Flag bits:
-			
-			000 -> No output
-			001 -> a > b
-			010 -> a < b
-			011 -> No output
-			100 -> a == b
-			101 -> a >= b
-			110 -> a <= b
-			111 -> No output
-			
-			*/
-			i_z <= (op[7:5] == 3'b000) || (op[7:5] == 3'b011) || (op[7:5] == 3'b111) ? 16'b0 : (op[5] && a > b) || (op[6] && a < b ) || (op[7] && a == b) ? 16'b1 : 16'b0;
-			i_flg <=
-					(a > b ? 8'b100 : 8'b0) | // a > b
-					(a == b ? 8'b1000 : 8'b0); // a == b
-		end
-		
-		// AND
-		5: begin
-			i_z <= a & b;
-			i_flg <= 8'b0;
-		end
-		
-		// OR
-		6: begin
-			i_z <= a | b;
-			i_flg <= 8'b0;
-		end
-		
-		// XOR
-		7: begin
-			i_z <= a ^ b;
-			i_flg <= 8'b0;
-		end
-		
-		// NOT
-		8: begin
-			i_z <= ~a;
-			i_flg <= 8'b0;
-		end
-		
-		// NAND
-		9: begin
-			i_z <= ~(a & b);
-			i_flg <= 8'b0;
-		end
-		
-		// NOR
-		10: begin
-			i_z <= ~(a | b);
-			i_flg <= 8'b0;
-		end
-		
-		// XNOR
-		11: begin
-			i_z <= ~(a ^ b);
-			i_flg <= 8'b0;
-		end
-		
-		// CL_MUL
-		12: begin
-			i_z <=
-				(a[7] ? b << 7 : 16'b0) ^
-				(a[6] ? b << 6 : 16'b0) ^
-				(a[5] ? b << 5 : 16'b0) ^
-				(a[4] ? b << 4 : 16'b0) ^
-				(a[3] ? b << 3 : 16'b0) ^
-				(a[2] ? b << 2 : 16'b0) ^
-				(a[1] ? b << 1 : 16'b0) ^
-				(a[0] ? b 		: 16'b0);
-			
-			i_flg <=
-				(a[7] && (b[1] || b[2] || b[3] || b[4] || b[5] || b[6] || b[7])) ||
-				(a[6] && (b[2] || b[3] || b[4] || b[5] || b[6] || b[7])) ||
-				(a[5] && (b[3] || b[4] || b[5] || b[6] || b[7])) ||
-				(a[4] && (b[4] || b[5] || b[6] || b[7])) ||
-				(a[3] && (b[5] || b[6] || b[7])) ||
-				(a[2] && (b[6] || b[7])) ||
-				(a[1] && b[7])
-				? 8'b1 : 8'b0;
-		end
-		default: begin
-			i_z <= 16'b0;
-			i_flg <= 8'b100000; // Unknown opcode
-		end
-	endcase
+   case(op & 8'b00011111) // 5-bit instructions: 3 flag bits
+      // ADD
+      0: begin
+         i_z <= add_out;
+         i_flg <= add_out[8] ? 8'b1 : 8'b0; // Set overflow flag if necessary
+      end
+      
+      // SUB
+      1: begin
+         i_z <= a-b;
+         i_flg <= i_z[15] << 1;
+      end
+      
+      // MUL
+      2: begin
+         i_z <= a*b;
+         i_flg <= i_z[15:8] != 8'b0 ? 8'b1 : 8'b0;
+      end
+      
+      // DIV
+      3: begin
+         if(b != 8'b0) begin
+            i_z <= a/b;
+            i_flg <= 8'b0;
+         end else begin
+            i_z <= 16'b0;
+            i_flg <= 8'b10000;
+         end
+      end
+      
+      // CMP
+      4: begin
+         /*
+         Flag bits:
+         
+         000 -> No output
+         001 -> a > b
+         010 -> a < b
+         011 -> No output
+         100 -> a == b
+         101 -> a >= b
+         110 -> a <= b
+         111 -> No output
+         
+         */
+         i_z <= (op[7:5] == 3'b000) || (op[7:5] == 3'b011) || (op[7:5] == 3'b111) ? 16'b0 : (op[5] && a > b) || (op[6] && a < b ) || (op[7] && a == b) ? 16'b1 : 16'b0;
+         i_flg <=
+               (a > b ? 8'b100 : 8'b0) | // a > b
+               (a == b ? 8'b1000 : 8'b0); // a == b
+      end
+      
+      // AND
+      5: begin
+         i_z <= a & b;
+         i_flg <= 8'b0;
+      end
+      
+      // OR
+      6: begin
+         i_z <= a | b;
+         i_flg <= 8'b0;
+      end
+      
+      // XOR
+      7: begin
+         i_z <= a ^ b;
+         i_flg <= 8'b0;
+      end
+      
+      // NOT
+      8: begin
+         i_z <= ~a;
+         i_flg <= 8'b0;
+      end
+      
+      // NAND
+      9: begin
+         i_z <= ~(a & b);
+         i_flg <= 8'b0;
+      end
+      
+      // NOR
+      10: begin
+         i_z <= ~(a | b);
+         i_flg <= 8'b0;
+      end
+      
+      // XNOR
+      11: begin
+         i_z <= ~(a ^ b);
+         i_flg <= 8'b0;
+      end
+      
+      // CL_MUL
+      12: begin
+         i_z <=
+            (a[7] ? b << 7 : 16'b0) ^
+            (a[6] ? b << 6 : 16'b0) ^
+            (a[5] ? b << 5 : 16'b0) ^
+            (a[4] ? b << 4 : 16'b0) ^
+            (a[3] ? b << 3 : 16'b0) ^
+            (a[2] ? b << 2 : 16'b0) ^
+            (a[1] ? b << 1 : 16'b0) ^
+            (a[0] ? b      : 16'b0);
+         
+         i_flg <=
+            (a[7] && (b[1] || b[2] || b[3] || b[4] || b[5] || b[6] || b[7])) ||
+            (a[6] && (b[2] || b[3] || b[4] || b[5] || b[6] || b[7])) ||
+            (a[5] && (b[3] || b[4] || b[5] || b[6] || b[7])) ||
+            (a[4] && (b[4] || b[5] || b[6] || b[7])) ||
+            (a[3] && (b[5] || b[6] || b[7])) ||
+            (a[2] && (b[6] || b[7])) ||
+            (a[1] && b[7])
+            ? 8'b1 : 8'b0;
+      end
+      
+      // SHR (flag: rotate)
+      13: begin
+         shift_rotate <= op[5];
+         i_z   <= b >= 8 ? 16'b0 : rshift[2];
+         i_flg <= rshift_underflow[0] || rshift_underflow[1] || rshift_underflow[2] || (b >= 8) ? 8'b10: 8'b0;
+      end
+      
+      // SHL (flag: rotate)
+      14: begin
+         shift_rotate <= op[5];
+         i_z   <= b >= 8 ? 16'b0 : lshift[2];
+         i_flg <= lshift_overflow[0] || lshift_overflow[1] || lshift_overflow[2] || (b >= 8) ? 8'b1 : 8'b0;
+      end
+      default: begin
+         i_z <= 16'b0;
+         i_flg <= 8'b100000; // Unknown opcode
+      end
+   endcase
 end
 
 endmodule
+
+
+// Bit shifters
+module LeftBitShifter(
+    input  wire [bits-1:0] data,
+    input  wire            doshift,
+    input  wire            rotate,
+    output wire [bits-1:0] out,
+    output wire            overflow
+);
+parameter bits;
+parameter shiftby;
+
+assign overflow = doshift && data[bits-1:shiftby] ? 1'b1 : 1'b0;
+assign out = doshift ? {data[bits-1-shiftby:0], rotate ? data[bits-1:bits-shiftby] : {shiftby{1'b0}}} : data;
+
+endmodule
+
+module RightBitShifter(
+    input  wire [bits-1:0] data,
+    input  wire            doshift,
+    input  wire            rotate,
+    output wire [bits-1:0] out,
+    output wire            underflow
+);
+parameter bits;
+parameter shiftby;
+
+assign underflow = doshift && data[shiftby:0] ? 1'b1 : 1'b0;
+assign out = doshift ? {rotate ? data[shiftby-1:0] : {shiftby{1'b0}}, data[bits-1:shiftby]} : data;
+
+endmodule
diff --git a/Callback.v b/Callback.v
new file mode 100644
index 0000000..210436e
--- /dev/null
+++ b/Callback.v
@@ -0,0 +1,24 @@
+module Callback(
+	input wire clk,
+	input wire [ISIZE-1:0] countdown,
+	input wire reset,
+	output wire callback
+);
+
+parameter ISIZE;
+
+reg [ISIZE-1:0] counter;
+reg [1:0] ctr_trigger = 2'b10;
+
+assign callback = !counter & ctr_trigger;
+
+always @(posedge clk or posedge reset) begin
+	if(reset) begin
+		counter <= countdown;
+		ctr_trigger <= 2'b10;
+	end
+	else if(counter) counter <= counter - 1'b1;
+	else if(ctr_trigger) ctr_trigger = ctr_trigger - 2'b01; // pull trigger high for 2 clock cycles to correct for 2.5ns pulse issues
+end
+
+endmodule
diff --git a/RAM.v b/RAM.v
index 4d92379..add717e 100644
--- a/RAM.v
+++ b/RAM.v
@@ -25,22 +25,21 @@ assign RAM_clk_enable = read_init != 3'b000;
 
 assign RAM_clk = clk;                    // RAM clock tracks processor input clock
 
-always @(posedge clk) begin
-	if(read_init) begin
-		read_init <= read_init + 3'b001;
-		RAM_state <= 4'b0001;              // STATE: read
-	end
-end
-
-always @(posedge read_rq) begin
-	if(!read_init && !write_rq) begin
-		read_init <= 3'b001;
+always @(posedge clk or posedge read_rq) begin
+   if(read_rq) begin
+      if(!read_init && !write_rq) begin
+         read_init <= 3'b001;
+      end
 	end
+   else if(read_init) begin
+      read_init <= read_init + 3'b001;
+      RAM_state <= 4'b0001;              // STATE: read
+   end
 end
 
 always @(posedge write_rq) begin
 	if(!read_init && !read_rq) begin
-		//TODO: Implement read
+      //TODO: Implement read
 	end
 end
 
diff --git a/SevenSegment.v b/SevenSegment.v
index ffc1a56..0f1deab 100644
--- a/SevenSegment.v
+++ b/SevenSegment.v
@@ -24,7 +24,8 @@ module SevenSegment(
 );
 
 // ----    SETTINGS    ---- //
-localparam PLL_SELECT = 3; // 0: 100MHz, 1: 200MHz, 2: 300MHz, 3: 400MHz, 4: 50MHz
+localparam PLL_SELECT = 1;  // 0: 100MHz, 1: 200MHz, 2: 300MHz, 3: 400MHz, 4: 50MHz
+localparam RAM_PLL = 0;     // Must be either 0 or 1. DO NOT SET TO ANY OTHER VALUE AS IT MIGHT FRY THE ONBOARD RAM!!!
 
 // ----    REGISTERS   ---- //
 reg       debounce;              // Input debouncer
@@ -42,6 +43,12 @@ wire [7:0] alu_out;              // ALU (core0) output
 wire [7:0] alu_flags;            // ALU (core0) output flags
 wire [4:0] pll;                  // Phase-locked-loop connections (+ source clock)
 wire       vga_clk;              // VGA data clock
+wire       cb;                   // Callback/timeout
+wire [9:0] vga_coords[0:1];      // Current screen coordinates being drawn to
+wire       ram_request_read;     // Trigger a read operation from main memory
+wire       ram_request_write;    // Trigger a write operation from main memory
+wire       ram_event;            // Event trigger from ram when an operation is completed (ex. a read op is ready)
+wire [3:0] ram_state;            // Main memory event information
 
 // ----  WIRE ASSIGNS  ---- //
 assign pll[4] = clk;
@@ -68,12 +75,39 @@ SegmentManager seg_display(
 	.segments (seg_write)
 );
 
-VGA screen(clk, gfx_rgb, vga_clk, VGA_rgb, VGA_hsync, VGA_vsync);
+// Graphics controller
+VGA screen(clk, gfx_rgb, vga_clk, vga_coords[0], vga_coords[1], VGA_rgb, VGA_hsync, VGA_vsync);
+
+// Arithmetic logic unit
 ALU core0(.a(alu_a), .b(alu_b), .op(alu_op), .z(alu_out), .o_flags(alu_flags));
+
+// Clock generator
 altpll0 pll_gen(clk, pll[0], pll[1], pll[2], pll[3]);
 
-always @(posedge vga_clk) gfx_rgb <= alu_a[2:0];
+// Callback module (generate timeouts) (Precision: 1/400M = 2.5ns)
+Callback #(.ISIZE(32)) timeout(pll[3], 32'd400000000, ~value, cb);
 
+// RAM module
+RAM main_memory(
+	pll[RAM_PLL],
+	RAM_addr,
+	RAM_A10,
+	RAM_bank_sel,
+	RAM_data,
+	RAM_clk,
+	RAM_clk_enable,
+	RAM_enable,
+	RAM_strobe_col,
+	RAM_strobe_row,
+	RAM_write_enable,
+	ram_request_read,
+	ram_request_write,
+	ram_state,
+	ram_event
+);
+
+always @(posedge cb or negedge value) select_out <= cb ? 4'b0000 : 4'b1111;
+always @(posedge vga_clk) gfx_rgb <= alu_a[2:0];
 always @(posedge pll[PLL_SELECT]) begin
 	if(!latch && write && next) begin
 		debounce <= 1'b1;
@@ -137,9 +171,9 @@ always @(posedge pll[PLL_SELECT]) begin
 		seg_buf_numbers[3] <= alu_flags[3:0];
 	end
 	
-	select_out[0] <= ~debounce;
-	select_out[1] <= write;
-	select_out[2] <= next;
-	select_out[3] <= latch;
+	//select_out[0] <= ~debounce;
+	//select_out[1] <= write;
+	//select_out[2] <= next;
+	//select_out[3] <= latch;
 end
 endmodule
diff --git a/VGA.v b/VGA.v
index f595759..ed1c8dc 100644
--- a/VGA.v
+++ b/VGA.v
@@ -2,6 +2,8 @@ module VGA(
 	input  wire       clk,
 	input wire [2:0]  rgb_data,
 	output reg        graphics_clk,
+	output wire [9:0] graphics_coords_x,
+	output wire [9:0] graphics_coords_y,
 	output wire [2:0] VGA_rgb,
 	output wire       VGA_hsync,
 	output wire       VGA_vsync
@@ -27,6 +29,8 @@ wire dat_act = ((hcount >= hdat_begin) && (hcount < hdat_end)) && ((vcount >= vd
 assign VGA_hsync = (hcount > hsync_end);
 assign VGA_vsync = (vcount > vsync_end);
 assign VGA_rgb = (dat_act) ?  rgb_data : 3'b0;
+assign graphics_coords_x = vcount;
+assign graphics_coords_y = hcount;
 
 // Clock divider
 always @(posedge clk) graphics_clk = ~graphics_clk;