summaryrefslogtreecommitdiffstats
path: root/aamux_controller.v
blob: 7bb095e5de992175cbbd6c9999947170fc8902b4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
// Copyright (c) 2014 Sergiusz 'q3k' BazaƄski <sergiusz@baznaski.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