aamux-dumper/aamux_controller.v

167 lines
3.6 KiB
Verilog

// Copyright (c) 2014 Sergiusz 'q3k' Bazański <sergiusz@bazanski.pl>
// Released under the 2-clause BSD license - see the COPYING file
`timescale 1ns / 1ps
`include "uart.v"
`include "sevenseg.v"
module aamux_controller(
// To the BIOS chip
input [7:0] data,
output reg [10:0] address,
output reg rowcol,
input busy,
// Debug LEDs
output [7:0] leds,
// Main system clock (50MHz)
input sys_clock,
// Reset button
input reset,
// UART TX&RX
output uart_signal_tx,
input uart_signal_rx,
// Seven-segment display
output [6:0] segments,
output [3:0] segments_anodes
);
/// Clocks
// Main clock (sys_clock/32)
reg [4:0] clock_counter;
wire clock = clock_counter[4];
// UART clock (toggle every 217 sys_clocks)
reg [7:0] uart_clock_counter;
reg uart_clock;
/// UART
reg uart_latch;
wire uart_received;
reg uart_received_clear;
wire [7:0] uart_rx;
wire uart_transmitted;
uart_controller uart(
.tx_data_in (data),
.tx_data_latch (uart_latch),
.clock (uart_clock),
.reset (reset),
.tx_transmitted (uart_transmitted),
.tx_signal (uart_signal_tx),
.rx_present (uart_received),
.rx_present_clear (uart_received_clear),
.rx_data (uart_rx),
.rx_signal (uart_signal_rx));
/// Seven-segment display
reg [15:0] to_display;
sevenseg display (
.value (to_display),
.segments (segments),
.anodes (segments_anodes),
.sys_clock (sys_clock),
.reset (reset));
/// State machine
reg [2:0] state;
`define WAIT_CMD 0
`define ASSERT_ROW 1
`define ROW_LATCH 2
`define ASSERT_COL 3
`define COL_LATCH 4
`define WAITING 5
`define OUTPUT 6
`define OUTPUT_WAIT 7
//assign leds = (1 << state);
assign leds = uart_received;
/// Address from which we will be reading, and
// how many bytes are left
reg [21:0] read_address;
reg [16:0] bytes_left;
/// sys_clock division into clock and uart_clock
always @(posedge sys_clock) begin
clock_counter <= clock_counter + 1;
if (uart_clock_counter >= 217) begin
uart_clock_counter <= 0;
uart_clock <= !uart_clock;
end else begin
uart_clock_counter <= uart_clock_counter + 1;
end
end
/// Main state machine code
always @(posedge clock) begin
if (reset) begin
// Reset state
state <= `WAIT_CMD;
read_address <= 0;
bytes_left <= 0;
rowcol <= 1;
uart_latch <= 0;
to_display <= 16'hDEAD;
uart_received_clear <= 0;
end else begin
case (state)
`WAIT_CMD: begin
if (uart_received) begin
state <= `ASSERT_ROW;
read_address <= uart_rx * 65536;
bytes_left <= 'h10000;
uart_received_clear <= 1;
end else
to_display <= 16'hDEAD;
end
`ASSERT_ROW: begin
address <= read_address[10:0];
state <= `ROW_LATCH;
rowcol <= 1;
end
`ROW_LATCH: begin
rowcol <= 0;
state <= `ASSERT_COL;
end
`ASSERT_COL: begin
address <= read_address[21:11];
state <= `COL_LATCH;
end
`COL_LATCH: begin
rowcol <= 1;
state <= `WAITING;
end
`WAITING: begin
if (busy)
state <= `OUTPUT;
end
// Wait for UART to be ready to latch data
`OUTPUT: begin
if (uart_transmitted) begin
uart_latch <= 1;
state <= `OUTPUT_WAIT;
end
end
// Wait for UART to latch our data and begin sending out
`OUTPUT_WAIT: begin
if (!uart_transmitted) begin
uart_latch <= 0;
to_display <= bytes_left;
read_address <= read_address + 1;
bytes_left <= bytes_left - 1;
if (bytes_left - 1 == 0) begin
uart_received_clear <= 0;
state <= `WAIT_CMD;
end else
state <= `ASSERT_ROW;
end
end
endcase
end
end
endmodule