Line 4... |
Line 4... |
//
|
//
|
// Project: XuLA2 board
|
// Project: XuLA2 board
|
//
|
//
|
// Purpose: Receive and decode inputs from a single UART line.
|
// Purpose: Receive and decode inputs from a single UART line.
|
//
|
//
|
|
//
|
// To interface with this module, connect it to your system clock,
|
// To interface with this module, connect it to your system clock,
|
// pass it the 32 bit setup register (defined below) and the UART
|
// pass it the 32 bit setup register (defined below) and the UART
|
// input. When data becomes available, the o_wr line will be asserted
|
// input. When data becomes available, the o_wr line will be asserted
|
// for one clock cycle. On parity or frame errors, the o_parity_err
|
// for one clock cycle. On parity or frame errors, the o_parity_err
|
// or o_frame_err lines will be asserted. Likewise, on a break
|
// or o_frame_err lines will be asserted. Likewise, on a break
|
Line 58... |
Line 59... |
// Creator: Dan Gisselquist, Ph.D.
|
// Creator: Dan Gisselquist, Ph.D.
|
// Gisselquist Technology, LLC
|
// Gisselquist Technology, LLC
|
//
|
//
|
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
//
|
//
|
// Copyright (C) 2015, Gisselquist Technology, LLC
|
// Copyright (C) 2015-2016, Gisselquist Technology, LLC
|
//
|
//
|
// This program is free software (firmware): you can redistribute it and/or
|
// This program is free software (firmware): you can redistribute it and/or
|
// modify it under the terms of the GNU General Public License as published
|
// modify it under the terms of the GNU General Public License as published
|
// by the Free Software Foundation, either version 3 of the License, or (at
|
// by the Free Software Foundation, either version 3 of the License, or (at
|
// your option) any later version.
|
// your option) any later version.
|
Line 70... |
Line 71... |
// This program is distributed in the hope that it will be useful, but WITHOUT
|
// This program is distributed in the hope that it will be useful, but WITHOUT
|
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
|
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
// for more details.
|
// for more details.
|
//
|
//
|
|
// You should have received a copy of the GNU General Public License along
|
|
// with this program. (It's in the $(ROOT)/doc directory, run make with no
|
|
// target there if the PDF file isn't present.) If not, see
|
|
// <http://www.gnu.org/licenses/> for a copy.
|
|
//
|
// License: GPL, v3, as defined and found on www.gnu.org,
|
// License: GPL, v3, as defined and found on www.gnu.org,
|
// http://www.gnu.org/licenses/gpl.html
|
// http://www.gnu.org/licenses/gpl.html
|
//
|
//
|
//
|
//
|
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
//
|
//
|
//
|
//
|
|
|
// States: (@ baud counter == 0)
|
// States: (@ baud counter == 0)
|
// 0 First bit arrives
|
// 0 First bit arrives
|
// ..7 Bits arrive
|
// ..7 Bits arrive
|
// 8 Stop bit (x1)
|
// 8 Stop bit (x1)
|
// 9 Stop bit (x2)
|
// 9 Stop bit (x2)
|
Line 142... |
Line 147... |
begin
|
begin
|
q_uart <= i_uart;
|
q_uart <= i_uart;
|
qq_uart <= q_uart;
|
qq_uart <= q_uart;
|
ck_uart <= qq_uart;
|
ck_uart <= qq_uart;
|
end
|
end
|
// assign o_ck_uart = ck_uart;
|
|
|
|
reg [27:0] chg_counter;
|
reg [27:0] chg_counter;
|
initial chg_counter = 28'h00;
|
initial chg_counter = 28'h00;
|
always @(posedge i_clk)
|
always @(posedge i_clk)
|
if (i_reset)
|
if (i_reset)
|
Line 154... |
Line 158... |
else if (qq_uart != ck_uart)
|
else if (qq_uart != ck_uart)
|
chg_counter <= 28'h00;
|
chg_counter <= 28'h00;
|
else if (chg_counter < break_condition)
|
else if (chg_counter < break_condition)
|
chg_counter <= chg_counter + 1;
|
chg_counter <= chg_counter + 1;
|
|
|
|
reg line_synch;
|
|
initial line_synch = 1'b0;
|
|
initial o_break = 1'b0;
|
always @(posedge i_clk)
|
always @(posedge i_clk)
|
o_break <=((chg_counter >= break_condition)&&(~ck_uart))? 1'b1:1'b0;
|
o_break <=((chg_counter >= break_condition)&&(~ck_uart))? 1'b1:1'b0;
|
|
always @(posedge i_clk)
|
|
line_synch <= ((chg_counter >= break_condition)&&(ck_uart));
|
|
|
reg [3:0] state;
|
reg [3:0] state;
|
reg [27:0] baud_counter;
|
reg [27:0] baud_counter;
|
reg [7:0] data_reg;
|
reg [7:0] data_reg;
|
reg calc_parity;
|
reg calc_parity, zero_baud_counter, half_baud_time;
|
initial o_wr = 1'b0;
|
initial o_wr = 1'b0;
|
initial state = `RXU_RESET_IDLE;
|
initial state = `RXU_RESET_IDLE;
|
initial o_parity_err = 1'b0;
|
initial o_parity_err = 1'b0;
|
initial o_frame_err = 1'b0;
|
initial o_frame_err = 1'b0;
|
// initial baud_counter = clocks_per_baud;
|
// initial baud_counter = clocks_per_baud;
|
Line 173... |
Line 182... |
if (i_reset)
|
if (i_reset)
|
begin
|
begin
|
o_wr <= 1'b0;
|
o_wr <= 1'b0;
|
o_data <= 8'h00;
|
o_data <= 8'h00;
|
state <= `RXU_RESET_IDLE;
|
state <= `RXU_RESET_IDLE;
|
baud_counter <= clocks_per_baud; // Set, not reset
|
baud_counter <= clocks_per_baud-28'h01;// Set, not reset
|
data_reg <= 8'h00;
|
data_reg <= 8'h00;
|
calc_parity <= 1'b0;
|
calc_parity <= 1'b0;
|
o_parity_err <= 1'b0;
|
o_parity_err <= 1'b0;
|
o_frame_err <= 1'b0;
|
o_frame_err <= 1'b0;
|
end else if (state == `RXU_RESET_IDLE)
|
end else if (state == `RXU_RESET_IDLE)
|
begin
|
begin
|
r_setup <= i_setup;
|
r_setup <= i_setup;
|
data_reg <= 8'h00; o_data <= 8'h00; o_wr <= 1'b0;
|
data_reg <= 8'h00; o_data <= 8'h00; o_wr <= 1'b0;
|
baud_counter <= clocks_per_baud-28'h01;// Set, not reset
|
baud_counter <= clocks_per_baud-28'h01;// Set, not reset
|
if ((ck_uart)&&(chg_counter >= break_condition))
|
if (line_synch)
|
// Goto idle state from a reset
|
// Goto idle state from a reset
|
state <= `RXU_IDLE;
|
state <= `RXU_IDLE;
|
else // Otherwise, stay in this condition 'til reset
|
else // Otherwise, stay in this condition 'til reset
|
state <= `RXU_RESET_IDLE;
|
state <= `RXU_RESET_IDLE;
|
calc_parity <= 1'b0;
|
calc_parity <= 1'b0;
|
o_parity_err <= 1'b0;
|
o_parity_err <= 1'b0;
|
o_frame_err <= 1'b0;
|
o_frame_err <= 1'b0;
|
end else if ((~ck_uart)&&(chg_counter >= break_condition))
|
end else if (o_break)
|
begin // We are in a break condition
|
begin // We are in a break condition
|
state <= `RXU_BREAK;
|
state <= `RXU_BREAK;
|
o_wr <= 1'b0;
|
o_wr <= 1'b0;
|
o_data <= 8'h00;
|
o_data <= 8'h00;
|
baud_counter <= clocks_per_baud-28'h01;// Set, not reset
|
baud_counter <= clocks_per_baud-28'h01;// Set, not reset
|
Line 219... |
Line 228... |
end else if (state == `RXU_IDLE)
|
end else if (state == `RXU_IDLE)
|
begin // Idle state, independent of baud counter
|
begin // Idle state, independent of baud counter
|
r_setup <= i_setup;
|
r_setup <= i_setup;
|
data_reg <= 8'h00; o_data <= 8'h00; o_wr <= 1'b0;
|
data_reg <= 8'h00; o_data <= 8'h00; o_wr <= 1'b0;
|
baud_counter <= clocks_per_baud - 28'h01;
|
baud_counter <= clocks_per_baud - 28'h01;
|
if ((ck_uart == 1'b0)&&(chg_counter > half_baud))
|
if ((~ck_uart)&&(half_baud_time))
|
begin
|
begin
|
// We are in the center of a valid start bit
|
// We are in the center of a valid start bit
|
case (data_bits)
|
case (data_bits)
|
2'b00: state <= `RXU_BIT_ZERO;
|
2'b00: state <= `RXU_BIT_ZERO;
|
2'b01: state <= `RXU_BIT_ONE;
|
2'b01: state <= `RXU_BIT_ONE;
|
Line 233... |
Line 242... |
end else // Otherwise, just stay here in idle
|
end else // Otherwise, just stay here in idle
|
state <= `RXU_IDLE;
|
state <= `RXU_IDLE;
|
calc_parity <= 1'b0;
|
calc_parity <= 1'b0;
|
o_parity_err <= 1'b0;
|
o_parity_err <= 1'b0;
|
o_frame_err <= 1'b0;
|
o_frame_err <= 1'b0;
|
end else if (baud_counter == 0)
|
end else if (zero_baud_counter)
|
begin
|
begin
|
baud_counter <= clocks_per_baud-28'h1;
|
baud_counter <= clocks_per_baud-28'h1;
|
if (state < `RXU_BIT_SEVEN)
|
if (state < `RXU_BIT_SEVEN)
|
begin
|
begin
|
// Data arrives least significant bit first.
|
// Data arrives least significant bit first.
|
Line 303... |
Line 312... |
o_parity_err <= 1'b0;
|
o_parity_err <= 1'b0;
|
o_frame_err <= 1'b0;
|
o_frame_err <= 1'b0;
|
end
|
end
|
end
|
end
|
|
|
|
initial zero_baud_counter = 1'b0;
|
|
always @(posedge i_clk)
|
|
zero_baud_counter <= (baud_counter == 28'h01);
|
|
|
|
initial half_baud_time = 0;
|
|
always @(posedge i_clk)
|
|
half_baud_time <= (~ck_uart)&&(chg_counter >= half_baud);
|
|
|
|
|
endmodule
|
endmodule
|
|
|
|
|
|
|
No newline at end of file
|
No newline at end of file
|