FreeCPU/SevenSegment.v
GabrielTofvesson e7f9e007d9 Added cache module
Update VGA module
  Quadrupled pixel clock
  Doubled resolution to 1280x800
Added ZigZag encode/decode to ALU
2018-10-18 03:08:06 +02:00

236 lines
8.5 KiB
Verilog

module SevenSegment(
input wire latch, // S4
input wire next, // S2
input wire value, // S3
output reg [3:0] select_out, // LED1-LED4 [0-3]
input wire write, // S1
input wire clk, // 50MHz clock
output [3:0] seg_select, // Q1-Q4 [0-3]
output [7:0] seg_write, // a-g + dp [0-7] + 8
output reg beep, // Buzzer
output wire [10:0] RAM_addr, // RAM address buffer
output wire RAM_A10, // RAM A10 precharge/address
output wire [1:0] RAM_bank_sel, // RAM bank selection
inout wire [15:0] RAM_data, // RAM data bus
output wire RAM_clk, // RAM clock signal
output wire RAM_clk_enable, // RAM enable clock
output wire RAM_enable, // RAM chip enable
output wire RAM_strobe_row, // RAM row strobe
output wire RAM_strobe_col, // RAM column strobe
output wire RAM_write_enable, // RAM data bus write enable
output wire VGA_vsync, // VGA display vsync trigger
output wire VGA_hsync, // VGA display hsync trigger
output wire [2:0] VGA_rgb // VGA color channels [0]: RED, [1]: GREEN, [2]: BLUE
);
// ---- SETTINGS ---- //
localparam PLL_SELECT = 3; // 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
reg db_trap; // Debounce buffer
reg [3:0] seg_buf_numbers [0:3];// 7-segment binary-number-representation buffer
reg [1:0] stage; // Computational stage
reg [7:0] alu_a; // ALU (core0) input a
reg [7:0] alu_b; // ALU (core0) input b
reg [7:0] alu_op; // ALU (core0) opcode
reg [2:0] gfx_rgb; // VGA color channels
reg [1:0] ram_bank_sel; // Which ram bank to access
reg [11:0] ram_addr; // RAM address selection
reg ram_close; // RAM close-row trigger
reg [7:0] cache0_addr; // Cache0 access address
reg [15:0] cache0_data = 16'b0; // Data to write to cache0
reg cache0_write; // Write-enable for cache0
// ---- WIRES ---- //
wire [7:0] seg_buf[0:3]; // Encoded segment buffer (8-bit expanded 4-bit number buffer)
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 [11: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 a r/w operation is ready
wire [1:0] ram_event_bank; // Which bank an event is happening on
wire [15:0] cache0_dq; // Data out from cache0
wire i_latch = ~latch; // Latch input wire
wire i_value = ~value; // Value input wire
wire i_next = ~next; // Next input wire
wire i_write = ~write; // Write input wire
// ---- WIRE ASSIGNS ---- //
assign pll[4] = clk;
// ---- INITIAL VALUES ---- //
initial select_out = 4'b1111;
initial debounce = 1'b0;
initial db_trap = 1'b1;
// Hex encoders for each 4-bit input set. Generates an 8-bit hex output
SegmentHexEncoder enc0(.number (seg_buf_numbers[0]), .encoded (seg_buf[0]));
SegmentHexEncoder enc1(.number (seg_buf_numbers[1]), .encoded (seg_buf[1]));
SegmentHexEncoder enc2(.number (seg_buf_numbers[2]), .encoded (seg_buf[2]));
SegmentHexEncoder enc3(.number (seg_buf_numbers[3]), .encoded (seg_buf[3]));
// A segment display manager to handle rendering data to the 7-segment displays
SegmentManager seg_display(
.clk (clk),
.segment_data0 (seg_buf[0]),
.segment_data1 (seg_buf[1]),
.segment_data2 (seg_buf[2]),
.segment_data3 (seg_buf[3]),
.segment_select (seg_select),
.segments (seg_write)
);
// 4096-bit internal cache memory
//cache c0(cache0_addr, pll[PLL_SELECT], cache0_data, cache0_write, cache0_dq);
// Graphics controller
VGA screen(pll[0], gfx_rgb, vga_clk, vga_coords[0], vga_coords[1], VGA_rgb, VGA_hsync, VGA_vsync);
// Arithmetic logic unit
ALU #(.BITS(8), .LOG2_BITS(3)) 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]);
// Callback module (generate timeouts) (Precision: 1/100M = 10ns) NOTE: 400MHz seems to be unstable, so a precision of 2.5ns comes at the price of stability
Callback #(.ISIZE(32)) timeout(pll[0], 32'd100000000, ~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_bank_sel,
ram_event,
ram_addr,
ram_close,
ram_event_bank
);
// 1280x800 screen
always @(posedge pll[3]) begin
gfx_rgb <= vga_coords[0] == 0 || vga_coords[0] == 1278 || vga_coords[1] == 0 || vga_coords[1] == 799 ? 3'b111 : 3'b0; // Draw border along edge of screen
end
always @(posedge i_latch or posedge i_write or posedge i_value or posedge i_next or posedge pll[PLL_SELECT]) begin
if(i_latch) debounce <= 1'b1;
else if(i_write) begin
debounce <= 1'b0;
if(debounce) begin
if(cache0_write) cache0_data <= cache0_data + 1'b1;
else cache0_write <= 1'b1;
end
end
else if(i_value) begin
debounce <= 1'b0;
if(debounce) begin
if(!cache0_write) cache0_addr <= cache0_addr + 1'b1;
else cache0_write <= 1'b0;
end
end
else if(i_next) begin
debounce <= 1'b0;
if(debounce) begin
if(!cache0_write) cache0_addr <= cache0_addr - 1'b1;
else cache0_write <= 1'b0;
end
end
else if(pll[PLL_SELECT]) begin
seg_buf_numbers[3] <= cache0_dq[3:0];
seg_buf_numbers[2] <= cache0_dq[7:4];
seg_buf_numbers[1] <= cache0_dq[11:8];
seg_buf_numbers[0] <= cache0_dq[15:12];
select_out <= {debounce ? 1'b0 : 1'b1, cache0_write ? 1'b0 : 1'b1, 2'b11};
end
end
/*
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;
end
if(write && next && db_trap) begin
debounce <= 1'b0;
db_trap <= 1'b0;
end
if(!write && debounce && !db_trap) begin
db_trap <= 1'b1;
if(stage == 2'b0) begin
alu_a <= alu_a + 8'b1;
end else if(stage == 2'b1) begin
alu_b <= alu_b + 8'b1;
end else if(stage == 2'b10) begin
alu_op <= alu_op + 8'b1;
end
end else if (!next && debounce && !db_trap) begin
db_trap <= 1'b1;
stage <= stage + 2'b1;
if(stage == 2'b01) begin
seg_buf_numbers[0] <= 4'b0;
seg_buf_numbers[1] <= 4'b0;
seg_buf_numbers[2] <= 4'b0;
seg_buf_numbers[3] <= 4'b0;
end
else if(stage == 2'b10) begin
seg_buf_numbers[0] <= alu_out[7:4];
seg_buf_numbers[1] <= alu_out[3:0];
seg_buf_numbers[2] <= alu_flags[7:4];
seg_buf_numbers[3] <= alu_flags[3:0];
end
else if(stage == 2'b11) begin
seg_buf_numbers[0] <= 4'b0;
seg_buf_numbers[1] <= 4'b0;
seg_buf_numbers[2] <= 4'b0;
seg_buf_numbers[3] <= 4'b0;
alu_a <= 8'b0;
alu_b <= 8'b0;
alu_op <= 8'b0;
end
end
if(stage == 2'b00 || stage == 2'b01) begin
seg_buf_numbers[0] <= alu_a[7:4];
seg_buf_numbers[1] <= alu_a[3:0];
seg_buf_numbers[2] <= alu_b[7:4];
seg_buf_numbers[3] <= alu_b[3:0];
end else if(stage == 2'b10) begin
seg_buf_numbers[0] <= alu_op[7:4];
seg_buf_numbers[1] <= alu_op[3:0];
seg_buf_numbers[2] <= 4'b0;
seg_buf_numbers[3] <= 4'b0;
end else if(stage == 2'b11) begin
seg_buf_numbers[0] <= alu_out[7:4];
seg_buf_numbers[1] <= alu_out[3:0];
seg_buf_numbers[2] <= alu_flags[7:4];
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;
end
*/
endmodule