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
|
// Top-level module for the iCE40 HX8K FPGA.
// This module instantiates the UART transmitter and sends the bytes for
// "Hello" and a newline character, then stops.
module top (
input SYSCLK, // 100 MHz system clock
input SERIAL_RX, // UART receive input
output SERIAL_TX, // UART transmit output
output LED1,
output LED2
);
// State machine states.
localparam RX_START = 0;
localparam WAIT_RX_DONE = 1;
localparam START_TX = 2;
localparam TX_IN_PROG = 3;
localparam WAIT_TX_DONE = 4;
localparam SEND_STRING_WELCOME = 5;
localparam RECEIVE_PROGRAM_DATA = 6;
reg [7:0] state = SEND_STRING_WELCOME;
// SEND_WELCOME data
`STR_welcome
reg [7:0] welcome_index = 0;
// Synchronous state machine with reset.
always @(posedge SYSCLK) begin
case (state)
// STATES FOR RX
RX_START: begin
if (!rx_done) begin
state <= WAIT_RX_DONE;
end
end
WAIT_RX_DONE: begin
if (rx_done) begin
state <= state_after_rx;
end
end
// STATES FOR TX
START_TX: begin
if (!tx_busy) begin
start_tx <= 1'b1; // trigger transmission
state <= TX_IN_PROG;
end
end
// After issuing the start pulse, wait for tx_busy to go high.
TX_IN_PROG: begin
start_tx <= 1'b0; // ensure pulse is only one cycle.
state <= WAIT_TX_DONE;
end
// Wait for the transmitter to finish sending the byte.
WAIT_TX_DONE: begin
if (!tx_busy) begin
state <= state_after_tx;
end
end
SEND_STRING_WELCOME: begin
if (welcome_index < 8'd`LEN_welcome) begin
data_tx <= str_welcome[welcome_index];
welcome_index <= welcome_index + 1;
state <= START_TX;
state_after_tx <= SEND_STRING_WELCOME;
end else begin
welcome_index <= 0;
state <= RECEIVE_PROGRAM_DATA;
state_after_tx <= RX_START;
end
end
RECEIVE_PROGRAM_DATA: begin
// TODO write data to flash
state <= RX_START;
state_after_rx <= RECEIVE_PROGRAM_DATA;
end
default: state <= RX_START;
endcase
end
// One-cycle pulse to trigger transmission.
reg start_tx = 1'b0;
// Data byte to be transmitted.
reg [7:0] data_tx = 8'b0;
// Busy flag from the transmitter.
wire tx_busy;
// State to transition to after TX done.
reg [7:0] state_after_tx = RX_START;
// Instantiate the UART transmitter.
uart_tx uart_inst (
.clk (SYSCLK),
.start(start_tx), // One-cycle pulse to start transmission.
.data (data_tx),
.tx (SERIAL_TX),
.busy (tx_busy)
);
wire [7:0] data_rx;
wire rx_done;
reg [7:0] state_after_rx = RECEIVE_PROGRAM_DATA;
uart_rx uart_rx_inst (
.clk (SYSCLK),
.rx (SERIAL_RX),
.data(data_rx),
.done(rx_done)
);
assign LED1 = 1;
assign LED2 = LED1;
endmodule
|