167 lines
3.6 KiB
Verilog
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
|