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
This commit is contained in:
parent
4642890198
commit
41f95d2077
323
ALU.v
323
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
|
||||
|
24
Callback.v
Normal file
24
Callback.v
Normal file
@ -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
|
21
RAM.v
21
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
|
||||
|
||||
|
@ -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
|
||||
|
4
VGA.v
4
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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user