//
|
//
|
// 16450 compatible UART with synchronous bus interface
|
// 16450 compatible UART with synchronous bus interface
|
// rclk/baudout is clk enable instead of actual clock
|
// rclk/baudout is clk enable instead of actual clock
|
//
|
//
|
// Copyright (c) 2005 Guy Hutchison (ghutchis@opencores.org)
|
// Copyright (c) 2005 Guy Hutchison (ghutchis@opencores.org)
|
// Based on VHDL 16450 UART by Daniel Wallner
|
// Based on VHDL 16450 UART by Daniel Wallner
|
//
|
//
|
// Permission is hereby granted, free of charge, to any person obtaining a
|
// Permission is hereby granted, free of charge, to any person obtaining a
|
// copy of this software and associated documentation files (the "Software"),
|
// copy of this software and associated documentation files (the "Software"),
|
// to deal in the Software without restriction, including without limitation
|
// to deal in the Software without restriction, including without limitation
|
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
// and/or sell copies of the Software, and to permit persons to whom the
|
// and/or sell copies of the Software, and to permit persons to whom the
|
// Software is furnished to do so, subject to the following conditions:
|
// Software is furnished to do so, subject to the following conditions:
|
//
|
//
|
// The above copyright notice and this permission notice shall be included
|
// The above copyright notice and this permission notice shall be included
|
// in all copies or substantial portions of the Software.
|
// in all copies or substantial portions of the Software.
|
//
|
//
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
module T16450
|
module T16450
|
(
|
(
|
input reset_n,
|
input reset_n,
|
input clk,
|
input clk,
|
input rclk,
|
input rclk,
|
input cs_n,
|
input cs_n,
|
input rd_n,
|
input rd_n,
|
input wr_n,
|
input wr_n,
|
input [2:0] addr,
|
input [2:0] addr,
|
input [7:0] wr_data,
|
input [7:0] wr_data,
|
output reg [7:0] rd_data,
|
output reg [7:0] rd_data,
|
input sin,
|
input sin,
|
input cts_n,
|
input cts_n,
|
input dsr_n,
|
input dsr_n,
|
input ri_n,
|
input ri_n,
|
input dcd_n,
|
input dcd_n,
|
output reg sout,
|
output reg sout,
|
output reg rts_n,
|
output reg rts_n,
|
output reg dtr_n,
|
output reg dtr_n,
|
output reg out1_n,
|
output reg out1_n,
|
output reg out2_n,
|
output reg out2_n,
|
output reg baudout,
|
output reg baudout,
|
output reg intr
|
output reg intr
|
);
|
);
|
|
|
reg [7:0] RBR; // Reciever Buffer Register
|
reg [7:0] RBR; // Reciever Buffer Register
|
reg [7:0] THR; // Transmitter Holding Register
|
reg [7:0] THR; // Transmitter Holding Register
|
reg [7:0] IER; // Interrupt Enable Register
|
reg [7:0] IER; // Interrupt Enable Register
|
reg [7:0] IIR; // Interrupt Ident. Register
|
reg [7:0] IIR; // Interrupt Ident. Register
|
reg [7:0] LCR; // Line Control Register
|
reg [7:0] LCR; // Line Control Register
|
reg [7:0] MCR; // MODEM Control Register
|
reg [7:0] MCR; // MODEM Control Register
|
reg [7:0] LSR; // Line Status Register
|
reg [7:0] LSR; // Line Status Register
|
reg [7:0] MSR; // MODEM Status Register
|
reg [7:0] MSR; // MODEM Status Register
|
reg [7:0] SCR; // Scratch Register
|
reg [7:0] SCR; // Scratch Register
|
reg [7:0] DLL; // Divisor Latch (LS)
|
reg [7:0] DLL; // Divisor Latch (LS)
|
reg [7:0] DLM; // Divisor Latch (MS)
|
reg [7:0] DLM; // Divisor Latch (MS)
|
|
|
reg [7:0] DM0;
|
reg [7:0] DM0;
|
reg [7:0] DM1;
|
reg [7:0] DM1;
|
|
|
reg [3:0] MSR_In;
|
reg [3:0] MSR_In;
|
|
|
reg [3:0] Bit_Phase;
|
reg [3:0] Bit_Phase;
|
reg [3:0] Brk_Cnt;
|
reg [3:0] Brk_Cnt;
|
reg RX_Filtered;
|
reg RX_Filtered;
|
reg [7:0] RX_ShiftReg;
|
reg [7:0] RX_ShiftReg;
|
reg [3:0] RX_Bit_Cnt;
|
reg [3:0] RX_Bit_Cnt;
|
reg RX_Parity;
|
reg RX_Parity;
|
reg RXD;
|
reg RXD;
|
|
|
reg TX_Tick;
|
reg TX_Tick;
|
reg [7:0] TX_ShiftReg;
|
reg [7:0] TX_ShiftReg;
|
reg [3:0] TX_Bit_Cnt;
|
reg [3:0] TX_Bit_Cnt;
|
reg TX_Parity;
|
reg TX_Parity;
|
reg TX_Next_Is_Stop;
|
reg TX_Next_Is_Stop;
|
reg TX_Stop_Bit;
|
reg TX_Stop_Bit;
|
reg TXD;
|
reg TXD;
|
|
|
always @*
|
always @*
|
begin
|
begin
|
dtr_n = MCR[4] || ~ MCR[0];
|
dtr_n = MCR[4] || ~ MCR[0];
|
rts_n = MCR[4] || ~ MCR[1];
|
rts_n = MCR[4] || ~ MCR[1];
|
out1_n = MCR[4] || ~ MCR[2];
|
out1_n = MCR[4] || ~ MCR[2];
|
out2_n = MCR[4] || ~ MCR[3];
|
out2_n = MCR[4] || ~ MCR[3];
|
sout = MCR[4] || (TXD && ~ LCR[6]);
|
sout = MCR[4] || (TXD && ~ LCR[6]);
|
if (!MCR[4]) RXD = sin;
|
if (!MCR[4]) RXD = sin;
|
else RXD = (TXD && !LCR[6]);
|
else RXD = (TXD && !LCR[6]);
|
|
|
intr = ~IIR[0];
|
intr = ~IIR[0];
|
|
|
if (LCR[7])
|
if (LCR[7])
|
begin
|
begin
|
DM0 = DLL;
|
DM0 = DLL;
|
DM1 = DLM;
|
DM1 = DLM;
|
end
|
end
|
else
|
else
|
begin
|
begin
|
DM0 = RBR;
|
DM0 = RBR;
|
DM1 = IER;
|
DM1 = IER;
|
end
|
end
|
|
|
case (addr)
|
case (addr)
|
3'h0 : rd_data = DM0;
|
3'h0 : rd_data = DM0;
|
3'h1 : rd_data = DM1;
|
3'h1 : rd_data = DM1;
|
3'h2 : rd_data = IIR;
|
3'h2 : rd_data = IIR;
|
3'h3 : rd_data = LCR;
|
3'h3 : rd_data = LCR;
|
3'h4 : rd_data = MCR;
|
3'h4 : rd_data = MCR;
|
3'h5 : rd_data = LSR;
|
3'h5 : rd_data = LSR;
|
3'h6 : rd_data = MSR;
|
3'h6 : rd_data = MSR;
|
default : rd_data = SCR;
|
default : rd_data = SCR;
|
endcase
|
endcase
|
end
|
end
|
|
|
always @ (posedge clk)
|
always @ (posedge clk)
|
begin
|
begin
|
if (!reset_n)
|
if (!reset_n)
|
begin
|
begin
|
THR <= #1 8'b00000000;
|
THR <= #1 8'b00000000;
|
IER <= #1 8'b00000000;
|
IER <= #1 8'b00000000;
|
LCR <= #1 8'b00000000;
|
LCR <= #1 8'b00000000;
|
MCR <= #1 8'b00000000;
|
MCR <= #1 8'b00000000;
|
MSR[3:0] <= #1 4'b0000;
|
MSR[3:0] <= #1 4'b0000;
|
SCR <= #1 8'b00000000;
|
SCR <= #1 8'b00000000;
|
DLL <= #1 8'b00000000;
|
DLL <= #1 8'b00000000;
|
DLM <= #1 8'b00000000;
|
DLM <= #1 8'b00000000;
|
end
|
end
|
else
|
else
|
begin
|
begin
|
if (!wr_n && !cs_n )
|
if (!wr_n && !cs_n )
|
begin
|
begin
|
case (addr)
|
case (addr)
|
3'b000 :
|
3'b000 :
|
begin
|
begin
|
if (LCR[7])
|
if (LCR[7])
|
DLL <= #1 wr_data;
|
DLL <= #1 wr_data;
|
else
|
else
|
THR <= #1 wr_data;
|
THR <= #1 wr_data;
|
end
|
end
|
3'b001 :
|
3'b001 :
|
begin
|
begin
|
if (LCR[7])
|
if (LCR[7])
|
DLM <= #1 wr_data;
|
DLM <= #1 wr_data;
|
else
|
else
|
IER[3:0] <= #1 wr_data[3:0];
|
IER[3:0] <= #1 wr_data[3:0];
|
end
|
end
|
3'b011 : LCR <= #1 wr_data;
|
3'b011 : LCR <= #1 wr_data;
|
3'b100 : MCR <= #1 wr_data;
|
3'b100 : MCR <= #1 wr_data;
|
3'b111 : SCR <= #1 wr_data;
|
3'b111 : SCR <= #1 wr_data;
|
default : ;
|
default : ;
|
endcase
|
endcase
|
end
|
end
|
if (!rd_n && !cs_n && (addr == 3'b110))
|
if (!rd_n && !cs_n && (addr == 3'b110))
|
MSR[3:0] <= #1 4'b0000;
|
MSR[3:0] <= #1 4'b0000;
|
if (MSR[4] != MSR_In[0])
|
if (MSR[4] != MSR_In[0])
|
MSR[0] <= #1 1'b1;
|
MSR[0] <= #1 1'b1;
|
if (MSR[5] != MSR_In[1])
|
if (MSR[5] != MSR_In[1])
|
MSR[1] <= #1 1'b1;
|
MSR[1] <= #1 1'b1;
|
if (!MSR[6] && MSR_In[2])
|
if (!MSR[6] && MSR_In[2])
|
MSR[2] <= #1 1'b1;
|
MSR[2] <= #1 1'b1;
|
if (MSR[7] != MSR_In[3])
|
if (MSR[7] != MSR_In[3])
|
MSR[3] <= #1 1'b1;
|
MSR[3] <= #1 1'b1;
|
end
|
end
|
end
|
end
|
always @ (posedge clk)
|
always @ (posedge clk)
|
begin
|
begin
|
if (!MCR[4])
|
if (!MCR[4])
|
begin
|
begin
|
MSR[4] <= #1 MSR_In[0];
|
MSR[4] <= #1 MSR_In[0];
|
MSR[5] <= #1 MSR_In[1];
|
MSR[5] <= #1 MSR_In[1];
|
MSR[6] <= #1 MSR_In[2];
|
MSR[6] <= #1 MSR_In[2];
|
MSR[7] <= #1 MSR_In[3];
|
MSR[7] <= #1 MSR_In[3];
|
end
|
end
|
else
|
else
|
begin
|
begin
|
MSR[4] <= #1 MCR[1];
|
MSR[4] <= #1 MCR[1];
|
MSR[5] <= #1 MCR[0];
|
MSR[5] <= #1 MCR[0];
|
MSR[6] <= #1 MCR[2];
|
MSR[6] <= #1 MCR[2];
|
MSR[7] <= #1 MCR[3];
|
MSR[7] <= #1 MCR[3];
|
end
|
end
|
MSR_In[0] <= #1 cts_n;
|
MSR_In[0] <= #1 cts_n;
|
MSR_In[1] <= #1 dsr_n;
|
MSR_In[1] <= #1 dsr_n;
|
MSR_In[2] <= #1 ri_n;
|
MSR_In[2] <= #1 ri_n;
|
MSR_In[3] <= #1 dcd_n;
|
MSR_In[3] <= #1 dcd_n;
|
end
|
end
|
|
|
always @*
|
always @*
|
begin
|
begin
|
IIR[7:3] <= #1 5'b00000;
|
IIR[7:3] = #1 5'b00000;
|
if (IER[2] && (LSR[4:1] != 4'b0000))
|
if (IER[2] && (LSR[4:1] != 4'b0000))
|
IIR[2:0] <= #1 3'b110;
|
IIR[2:0] = #1 3'b110;
|
else if (IER[0] && LSR[0])
|
else if (IER[0] && LSR[0])
|
IIR[2:0] <= #1 3'b100;
|
IIR[2:0] = #1 3'b100;
|
else if (IER[1] && LSR[5])
|
else if (IER[1] && LSR[5])
|
IIR[2:0] <= #1 3'b010;
|
IIR[2:0] = #1 3'b010;
|
else if (IER[3] && ((!MCR[4] && (MSR[3:0] != 0)) || (MCR[4] && (MCR[3:0] != 0))))
|
else if (IER[3] && ((!MCR[4] && (MSR[3:0] != 0)) || (MCR[4] && (MCR[3:0] != 0))))
|
IIR[2:0] <= #1 3'b000;
|
IIR[2:0] = #1 3'b000;
|
else
|
else
|
IIR[2:0] <= #1 3'b001;
|
IIR[2:0] = #1 3'b001;
|
end
|
end
|
|
|
// Baud x 16 clock generator
|
// Baud x 16 clock generator
|
always @ (posedge clk)
|
always @ (posedge clk)
|
begin : clk_gen
|
begin : clk_gen
|
reg [15:0] Baud_Cnt;
|
reg [15:0] Baud_Cnt;
|
if (!reset_n)
|
if (!reset_n)
|
begin
|
begin
|
Baud_Cnt = 16'b0000000000000000;
|
Baud_Cnt = 16'b0000000000000000;
|
baudout <= #1 1'b0;
|
baudout <= #1 1'b0;
|
end
|
end
|
else
|
else
|
begin
|
begin
|
if ((Baud_Cnt[15:1] == 15'h0) ||
|
if ((Baud_Cnt[15:1] == 15'h0) ||
|
(!wr_n && !cs_n && (addr[2:1] == 2'b00) && LCR[7]) )
|
(!wr_n && !cs_n && (addr[2:1] == 2'b00) && LCR[7]) )
|
begin
|
begin
|
Baud_Cnt[15:8] = DLM;
|
Baud_Cnt[15:8] = DLM;
|
Baud_Cnt[7:0] = DLL;
|
Baud_Cnt[7:0] = DLL;
|
baudout <= #1 1'b1;
|
baudout <= #1 1'b1;
|
end
|
end
|
else
|
else
|
begin
|
begin
|
Baud_Cnt = Baud_Cnt - 1;
|
Baud_Cnt = Baud_Cnt - 1;
|
baudout <= #1 1'b0;
|
baudout <= #1 1'b0;
|
end
|
end
|
end
|
end
|
end
|
end
|
|
|
// Input filter
|
// Input filter
|
always @ (posedge clk)
|
always @ (posedge clk)
|
begin : input_filter
|
begin : input_filter
|
reg [1:0] Samples;
|
reg [1:0] Samples;
|
if (!reset_n)
|
if (!reset_n)
|
begin
|
begin
|
Samples = 2'b11;
|
Samples = 2'b11;
|
RX_Filtered <= #1 1'b1;
|
RX_Filtered <= #1 1'b1;
|
end
|
end
|
else
|
else
|
begin
|
begin
|
if (rclk)
|
if (rclk)
|
begin
|
begin
|
Samples[1] = Samples[0];
|
Samples[1] = Samples[0];
|
Samples[0] = RXD;
|
Samples[0] = RXD;
|
end
|
end
|
if (Samples == 2'b00)
|
if (Samples == 2'b00)
|
begin
|
begin
|
RX_Filtered <= #1 1'b0;
|
RX_Filtered <= #1 1'b0;
|
end
|
end
|
if (Samples == 2'b11)
|
if (Samples == 2'b11)
|
begin
|
begin
|
RX_Filtered <= #1 1'b1;
|
RX_Filtered <= #1 1'b1;
|
end
|
end
|
end
|
end
|
end
|
end
|
|
|
// Receive state machine
|
// Receive state machine
|
always @ (posedge clk)
|
always @ (posedge clk)
|
begin
|
begin
|
if (!reset_n)
|
if (!reset_n)
|
begin
|
begin
|
RBR <= #1 8'b00000000;
|
RBR <= #1 8'b00000000;
|
LSR[4:0] <= #1 5'b00000;
|
LSR[4:0] <= #1 5'b00000;
|
Bit_Phase <= #1 4'b0000;
|
Bit_Phase <= #1 4'b0000;
|
Brk_Cnt <= #1 4'b0000;
|
Brk_Cnt <= #1 4'b0000;
|
RX_ShiftReg[7:0] <= #1 8'b00000000;
|
RX_ShiftReg[7:0] <= #1 8'b00000000;
|
RX_Bit_Cnt <= #1 0;
|
RX_Bit_Cnt <= #1 0;
|
RX_Parity <= #1 1'b0;
|
RX_Parity <= #1 1'b0;
|
end
|
end
|
else
|
else
|
begin
|
begin
|
if (addr == 3'b000 && !LCR[7] && !rd_n && !cs_n )
|
if (addr == 3'b000 && !LCR[7] && !rd_n && !cs_n )
|
begin
|
begin
|
LSR[0] <= #1 1'b0; // DR
|
LSR[0] <= #1 1'b0; // DR
|
end
|
end
|
if (addr == 3'b101 && !rd_n && !cs_n )
|
if (addr == 3'b101 && !rd_n && !cs_n )
|
begin
|
begin
|
LSR[4] <= #1 1'b0; // BI
|
LSR[4] <= #1 1'b0; // BI
|
LSR[3] <= #1 1'b0; // FE
|
LSR[3] <= #1 1'b0; // FE
|
LSR[2] <= #1 1'b0; // PE
|
LSR[2] <= #1 1'b0; // PE
|
LSR[1] <= #1 1'b0; // OE
|
LSR[1] <= #1 1'b0; // OE
|
end
|
end
|
if (rclk)
|
if (rclk)
|
begin
|
begin
|
if (!RX_Bit_Cnt && (RX_Filtered || (Bit_Phase == 4'b0111)))
|
if ((RX_Bit_Cnt == 0) && (RX_Filtered || (Bit_Phase == 4'b0111)))
|
begin
|
begin
|
Bit_Phase <= #1 4'b0000;
|
Bit_Phase <= #1 4'b0000;
|
end
|
end
|
else
|
else
|
begin
|
begin
|
Bit_Phase <= #1 Bit_Phase + 1;
|
Bit_Phase <= #1 Bit_Phase + 1;
|
end
|
end
|
if (Bit_Phase == 4'b1111 )
|
if (Bit_Phase == 4'b1111 )
|
begin
|
begin
|
if (RX_Filtered)
|
if (RX_Filtered)
|
begin
|
begin
|
Brk_Cnt <= #1 4'b0000;
|
Brk_Cnt <= #1 4'b0000;
|
end
|
end
|
else
|
else
|
begin
|
begin
|
Brk_Cnt <= #1 Brk_Cnt + 1;
|
Brk_Cnt <= #1 Brk_Cnt + 1;
|
end
|
end
|
if (Brk_Cnt == 4'b1100)
|
if (Brk_Cnt == 4'b1100)
|
begin
|
begin
|
LSR[4] <= #1 1'b1; // BI
|
LSR[4] <= #1 1'b1; // BI
|
end
|
end
|
end
|
end
|
if (!RX_Bit_Cnt )
|
if (RX_Bit_Cnt == 0)
|
begin
|
begin
|
if (Bit_Phase == 4'b0111)
|
if (Bit_Phase == 4'b0111)
|
begin
|
begin
|
RX_Bit_Cnt <= #1 RX_Bit_Cnt + 1;
|
RX_Bit_Cnt <= #1 RX_Bit_Cnt + 1;
|
RX_Parity <= #1 ! LCR[4]; // EPS
|
RX_Parity <= #1 ! LCR[4]; // EPS
|
end
|
end
|
end
|
end
|
else if (Bit_Phase == 4'b1111)
|
else if (Bit_Phase == 4'b1111)
|
begin
|
begin
|
RX_Bit_Cnt <= #1 RX_Bit_Cnt + 1;
|
RX_Bit_Cnt <= #1 RX_Bit_Cnt + 1;
|
if (RX_Bit_Cnt == 10 )
|
if (RX_Bit_Cnt == 10 )
|
begin // Parity stop bit
|
begin // Parity stop bit
|
RX_Bit_Cnt <= #1 0;
|
RX_Bit_Cnt <= #1 0;
|
LSR[0] <= #1 1'b1; // UART Receive complete
|
LSR[0] <= #1 1'b1; // UART Receive complete
|
LSR[3] <= #1 ~RX_Filtered; // Framing error
|
LSR[3] <= #1 ~RX_Filtered; // Framing error
|
end
|
end
|
else if ((RX_Bit_Cnt == 9 && LCR[1:0] == 2'b11) ||
|
else if ((RX_Bit_Cnt == 9 && LCR[1:0] == 2'b11) ||
|
(RX_Bit_Cnt == 8 && LCR[1:0] == 2'b10) ||
|
(RX_Bit_Cnt == 8 && LCR[1:0] == 2'b10) ||
|
(RX_Bit_Cnt == 7 && LCR[1:0] == 2'b01) ||
|
(RX_Bit_Cnt == 7 && LCR[1:0] == 2'b01) ||
|
(RX_Bit_Cnt == 6 && LCR[1:0] == 2'b00) )
|
(RX_Bit_Cnt == 6 && LCR[1:0] == 2'b00) )
|
begin // Stop bit/Parity
|
begin // Stop bit/Parity
|
RX_Bit_Cnt <= #1 0;
|
RX_Bit_Cnt <= #1 0;
|
if (LCR[3])
|
if (LCR[3])
|
begin // PEN
|
begin // PEN
|
RX_Bit_Cnt <= #1 10;
|
RX_Bit_Cnt <= #1 10;
|
if (LCR[5])
|
if (LCR[5])
|
begin // Stick parity
|
begin // Stick parity
|
if (RX_Filtered == LCR[4])
|
if (RX_Filtered == LCR[4])
|
begin
|
begin
|
LSR[2] <= #1 1'b1;
|
LSR[2] <= #1 1'b1;
|
end
|
end
|
end
|
end
|
else
|
else
|
begin
|
begin
|
if (RX_Filtered != RX_Parity)
|
if (RX_Filtered != RX_Parity)
|
begin
|
begin
|
LSR[2] <= #1 1'b1;
|
LSR[2] <= #1 1'b1;
|
end
|
end
|
end
|
end
|
end
|
end
|
else
|
else
|
begin
|
begin
|
LSR[0] <= #1 1'b1; // UART Receive complete
|
LSR[0] <= #1 1'b1; // UART Receive complete
|
LSR[3] <= #1 ~RX_Filtered; // Framing error
|
LSR[3] <= #1 ~RX_Filtered; // Framing error
|
end
|
end
|
RBR <= #1 RX_ShiftReg[7:0];
|
RBR <= #1 RX_ShiftReg[7:0];
|
LSR[1] <= #1 LSR[0];
|
LSR[1] <= #1 LSR[0];
|
if (addr == 3'b101 && !rd_n && !cs_n )
|
if (addr == 3'b101 && !rd_n && !cs_n )
|
begin
|
begin
|
LSR[1] <= #1 1'b0;
|
LSR[1] <= #1 1'b0;
|
end
|
end
|
end
|
end
|
else
|
else
|
begin
|
begin
|
RX_ShiftReg[6:0] <= #1 RX_ShiftReg[7:1];
|
RX_ShiftReg[6:0] <= #1 RX_ShiftReg[7:1];
|
RX_ShiftReg[7] <= #1 RX_Filtered;
|
RX_ShiftReg[7] <= #1 RX_Filtered;
|
if (LCR[1:0] == 2'b10)
|
if (LCR[1:0] == 2'b10)
|
begin
|
begin
|
RX_ShiftReg[7] <= #1 1'b0;
|
RX_ShiftReg[7] <= #1 1'b0;
|
RX_ShiftReg[6] <= #1 RX_Filtered;
|
RX_ShiftReg[6] <= #1 RX_Filtered;
|
end
|
end
|
if (LCR[1:0] == 2'b01)
|
if (LCR[1:0] == 2'b01)
|
begin
|
begin
|
RX_ShiftReg[7] <= #1 1'b0;
|
RX_ShiftReg[7] <= #1 1'b0;
|
RX_ShiftReg[6] <= #1 1'b0;
|
RX_ShiftReg[6] <= #1 1'b0;
|
RX_ShiftReg[5] <= #1 RX_Filtered;
|
RX_ShiftReg[5] <= #1 RX_Filtered;
|
end
|
end
|
if (LCR[1:0] == 2'b00)
|
if (LCR[1:0] == 2'b00)
|
begin
|
begin
|
RX_ShiftReg[7] <= #1 1'b0;
|
RX_ShiftReg[7] <= #1 1'b0;
|
RX_ShiftReg[6] <= #1 1'b0;
|
RX_ShiftReg[6] <= #1 1'b0;
|
RX_ShiftReg[5] <= #1 1'b0;
|
RX_ShiftReg[5] <= #1 1'b0;
|
RX_ShiftReg[4] <= #1 RX_Filtered;
|
RX_ShiftReg[4] <= #1 RX_Filtered;
|
end
|
end
|
RX_Parity <= #1 RX_Filtered ^ RX_Parity;
|
RX_Parity <= #1 RX_Filtered ^ RX_Parity;
|
end
|
end
|
end
|
end
|
end
|
end
|
end
|
end
|
end
|
end
|
|
|
// Transmit bit tick
|
// Transmit bit tick
|
always @ (posedge clk)
|
always @ (posedge clk)
|
begin : bit_tick
|
begin : bit_tick
|
reg [4:0] TX_Cnt;
|
reg [4:0] TX_Cnt;
|
if (!reset_n)
|
if (!reset_n)
|
begin
|
begin
|
TX_Cnt = 5'b00000;
|
TX_Cnt = 5'b00000;
|
TX_Tick <= #1 1'b0;
|
TX_Tick <= #1 1'b0;
|
end
|
end
|
else
|
else
|
begin
|
begin
|
TX_Tick <= #1 1'b0;
|
TX_Tick <= #1 1'b0;
|
if (rclk)
|
if (rclk)
|
begin
|
begin
|
TX_Cnt = TX_Cnt + 1;
|
TX_Cnt = TX_Cnt + 1;
|
if (LCR[2] && TX_Stop_Bit)
|
if (LCR[2] && TX_Stop_Bit)
|
begin
|
begin
|
if (LCR[1:0] == 2'b00)
|
if (LCR[1:0] == 2'b00)
|
begin
|
begin
|
if (TX_Cnt == 5'b10111)
|
if (TX_Cnt == 5'b10111)
|
begin
|
begin
|
TX_Tick <= #1 1'b1;
|
TX_Tick <= #1 1'b1;
|
TX_Cnt[3:0] = 4'b0000;
|
TX_Cnt[3:0] = 4'b0000;
|
end
|
end
|
end
|
end
|
else
|
else
|
begin
|
begin
|
if (TX_Cnt == 5'b11111)
|
if (TX_Cnt == 5'b11111)
|
begin
|
begin
|
TX_Tick <= #1 1'b1;
|
TX_Tick <= #1 1'b1;
|
TX_Cnt[3:0] = 4'b0000;
|
TX_Cnt[3:0] = 4'b0000;
|
end
|
end
|
end
|
end
|
end
|
end
|
else
|
else
|
begin
|
begin
|
TX_Cnt[4] = 1'b1;
|
TX_Cnt[4] = 1'b1;
|
if (TX_Cnt[3:0] == 4'b1111)
|
if (TX_Cnt[3:0] == 4'b1111)
|
begin
|
begin
|
TX_Tick <= #1 1'b1;
|
TX_Tick <= #1 1'b1;
|
end
|
end
|
end
|
end
|
end
|
end
|
end
|
end
|
end
|
end
|
|
|
// Transmit state machine
|
// Transmit state machine
|
always @ (posedge clk)
|
always @ (posedge clk)
|
begin
|
begin
|
if (!reset_n)
|
if (!reset_n)
|
begin
|
begin
|
LSR[7:5] <= #1 3'b011;
|
LSR[7:5] <= #1 3'b011;
|
TX_Bit_Cnt <= #1 0;
|
TX_Bit_Cnt <= #1 0;
|
TX_ShiftReg <= #1 0;
|
TX_ShiftReg <= #1 0;
|
TXD <= #1 1'b1;
|
TXD <= #1 1'b1;
|
TX_Parity <= #1 1'b0;
|
TX_Parity <= #1 1'b0;
|
TX_Next_Is_Stop <= #1 1'b0;
|
TX_Next_Is_Stop <= #1 1'b0;
|
TX_Stop_Bit <= #1 1'b0;
|
TX_Stop_Bit <= #1 1'b0;
|
end
|
end
|
else
|
else
|
begin
|
begin
|
if (TX_Tick == 1'b1)
|
if (TX_Tick == 1'b1)
|
begin
|
begin
|
TX_Next_Is_Stop <= #1 1'b0;
|
TX_Next_Is_Stop <= #1 1'b0;
|
TX_Stop_Bit <= #1 TX_Next_Is_Stop;
|
TX_Stop_Bit <= #1 TX_Next_Is_Stop;
|
case (TX_Bit_Cnt)
|
case (TX_Bit_Cnt)
|
0 :
|
0 :
|
begin
|
begin
|
if (!LSR[5])
|
if (!LSR[5])
|
begin // THRE
|
begin // THRE
|
TX_Bit_Cnt <= #1 1;
|
TX_Bit_Cnt <= #1 1;
|
end
|
end
|
TXD <= #1 1'b1;
|
TXD <= #1 1'b1;
|
end
|
end
|
1 : // Start bit
|
1 : // Start bit
|
begin
|
begin
|
TX_ShiftReg[7:0] <= #1 THR;
|
TX_ShiftReg[7:0] <= #1 THR;
|
LSR[5] <= #1 1'b1; // THRE
|
LSR[5] <= #1 1'b1; // THRE
|
TXD <= #1 1'b0;
|
TXD <= #1 1'b0;
|
TX_Parity <= #1 ~LCR[4]; // EPS
|
TX_Parity <= #1 ~LCR[4]; // EPS
|
TX_Bit_Cnt <= #1 TX_Bit_Cnt + 1;
|
TX_Bit_Cnt <= #1 TX_Bit_Cnt + 1;
|
end
|
end
|
10 : // Parity bit
|
10 : // Parity bit
|
begin
|
begin
|
TXD <= #1 TX_Parity;
|
TXD <= #1 TX_Parity;
|
if (LCR[5] == 1'b1 )
|
if (LCR[5] == 1'b1 )
|
begin // Stick parity
|
begin // Stick parity
|
TXD <= #1 ~LCR[4];
|
TXD <= #1 ~LCR[4];
|
end
|
end
|
TX_Bit_Cnt <= #1 0;
|
TX_Bit_Cnt <= #1 0;
|
TX_Next_Is_Stop <= #1 1'b1;
|
TX_Next_Is_Stop <= #1 1'b1;
|
end
|
end
|
default :
|
default :
|
begin
|
begin
|
TX_Bit_Cnt <= #1 TX_Bit_Cnt + 1;
|
TX_Bit_Cnt <= #1 TX_Bit_Cnt + 1;
|
if ((TX_Bit_Cnt == 9 && LCR[1:0] == 2'b11) ||
|
if ((TX_Bit_Cnt == 9 && LCR[1:0] == 2'b11) ||
|
(TX_Bit_Cnt == 8 && LCR[1:0] == 2'b10) ||
|
(TX_Bit_Cnt == 8 && LCR[1:0] == 2'b10) ||
|
(TX_Bit_Cnt == 7 && LCR[1:0] == 2'b01) ||
|
(TX_Bit_Cnt == 7 && LCR[1:0] == 2'b01) ||
|
(TX_Bit_Cnt == 6 && LCR[1:0] == 2'b00) )
|
(TX_Bit_Cnt == 6 && LCR[1:0] == 2'b00) )
|
begin
|
begin
|
TX_Bit_Cnt <= #1 0;
|
TX_Bit_Cnt <= #1 0;
|
if (LCR[3] == 1'b1 )
|
if (LCR[3] == 1'b1 )
|
begin // PEN
|
begin // PEN
|
TX_Bit_Cnt <= #1 10;
|
TX_Bit_Cnt <= #1 10;
|
end
|
end
|
else
|
else
|
begin
|
begin
|
TX_Next_Is_Stop <= #1 1'b1;
|
TX_Next_Is_Stop <= #1 1'b1;
|
end
|
end
|
LSR[6] <= #1 1'b1; // TEMT
|
LSR[6] <= #1 1'b1; // TEMT
|
end
|
end
|
TXD <= #1 TX_ShiftReg[0];
|
TXD <= #1 TX_ShiftReg[0];
|
TX_ShiftReg[6:0] <= #1 TX_ShiftReg[7:1];
|
TX_ShiftReg[6:0] <= #1 TX_ShiftReg[7:1];
|
TX_Parity <= #1 TX_ShiftReg[0] ^ TX_Parity;
|
TX_Parity <= #1 TX_ShiftReg[0] ^ TX_Parity;
|
end
|
end
|
endcase
|
endcase
|
end
|
end
|
if (!wr_n && !cs_n && addr == 3'b000 && !LCR[7] )
|
if (!wr_n && !cs_n && addr == 3'b000 && !LCR[7] )
|
begin
|
begin
|
LSR[5] <= #1 1'b0; // THRE
|
LSR[5] <= #1 1'b0; // THRE
|
LSR[6] <= #1 1'b0; // TEMT
|
LSR[6] <= #1 1'b0; // TEMT
|
end
|
end
|
end
|
end
|
end
|
end
|
|
|
endmodule
|
endmodule
|
|
|
|
|