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;