244 lines
6.1 KiB
Plaintext
244 lines
6.1 KiB
Plaintext
|
package UART;
|
||
|
|
||
|
import Cntrs::*;
|
||
|
import GetPut::*;
|
||
|
import FIFOF::*;
|
||
|
import SpecialFIFOs::*;
|
||
|
import StmtFSM::*;
|
||
|
import Connectable::*;
|
||
|
|
||
|
import PinSync::*;
|
||
|
import GlitchFilter::*;
|
||
|
import Strobe::*;
|
||
|
|
||
|
(* always_enabled *)
|
||
|
interface UART_RX_PHY;
|
||
|
(* prefix="" *)
|
||
|
method Action rx_in((* port="rx_in" *) bit b);
|
||
|
(* result="cts" *)
|
||
|
method Bool stop_sending();
|
||
|
endinterface
|
||
|
|
||
|
(* always_enabled *)
|
||
|
interface UART_TX_PHY;
|
||
|
(* result="tx_out" *)
|
||
|
method bit tx_out();
|
||
|
(* prefix="" *)
|
||
|
method Action can_send((* port="rts" *) Bool send);
|
||
|
endinterface
|
||
|
|
||
|
(* always_enabled *)
|
||
|
interface UART_PHY;
|
||
|
(* prefix="" *)
|
||
|
method Action rx_in((* port="rx_in" *) bit b);
|
||
|
(* result="tx_out" *)
|
||
|
method bit tx_out();
|
||
|
(* result="cts" *)
|
||
|
method Bool stop_sending();
|
||
|
(* prefix="" *)
|
||
|
method Action can_send((* port="rts" *) Bool send);
|
||
|
endinterface
|
||
|
|
||
|
interface UART_RX;
|
||
|
interface UART_RX_PHY phy;
|
||
|
interface Get#(Bit#(8)) receive;
|
||
|
endinterface
|
||
|
|
||
|
interface UART_TX;
|
||
|
interface UART_TX_PHY phy;
|
||
|
interface Put#(Bit#(8)) send;
|
||
|
endinterface
|
||
|
|
||
|
interface UART;
|
||
|
interface UART_PHY phy;
|
||
|
interface Put#(Bit#(8)) send;
|
||
|
interface Get#(Bit#(8)) receive;
|
||
|
endinterface
|
||
|
|
||
|
typedef enum {
|
||
|
WaitIdle,
|
||
|
Idle,
|
||
|
Read,
|
||
|
Stop,
|
||
|
Cork
|
||
|
} RXState deriving (Bits, Eq);
|
||
|
|
||
|
module mkUARTReceiver(Integer clock_frequency, Integer uart_bitrate, UART_RX ifc);
|
||
|
Reg#(bit) rx_sync <- mkPinSync(0);
|
||
|
let rx_in <- mkGlitchFilter(3, 0);
|
||
|
mkConnection(toGet(asReg(rx_sync)), toPut(asReg(rx_in)));
|
||
|
|
||
|
Reg#(RXState) rx_state <- mkReg(WaitIdle);
|
||
|
Strobe bit_16x_strobe <- mkStrobe(clock_frequency, 16*uart_bitrate);
|
||
|
Count#(UInt#(4)) cnt <- mkCount(0);
|
||
|
Reg#(Bit#(8)) shift_in <- mkReg(0);
|
||
|
FIFOF#(Bit#(8)) rx <- mkBypassFIFOF();
|
||
|
|
||
|
(* no_implicit_conditions, fire_when_enabled *)
|
||
|
rule rx_counter (bit_16x_strobe);
|
||
|
cnt.incr(1);
|
||
|
endrule
|
||
|
|
||
|
(* no_implicit_conditions, fire_when_enabled *)
|
||
|
rule rx_wait_idle (rx_state == WaitIdle && bit_16x_strobe && rx_in == 1);
|
||
|
rx_state <= Idle;
|
||
|
endrule
|
||
|
|
||
|
(* no_implicit_conditions, fire_when_enabled *)
|
||
|
rule rx_idle (rx_state == Idle && bit_16x_strobe && rx_in == 0);
|
||
|
rx_state <= Read;
|
||
|
cnt <= 1;
|
||
|
shift_in <= 8'hFF;
|
||
|
endrule
|
||
|
|
||
|
(* no_implicit_conditions, fire_when_enabled *)
|
||
|
rule rx_read (rx_state == Read && bit_16x_strobe && cnt == 7);
|
||
|
let shifted_out = shift_in[0];
|
||
|
shift_in <= {rx_in, shift_in[7:1]};
|
||
|
if (shifted_out == 0) begin // start bit reached end of shiftreg
|
||
|
rx_state <= Stop;
|
||
|
end
|
||
|
endrule
|
||
|
|
||
|
(* fire_when_enabled *)
|
||
|
rule rx_stop (rx_state == Stop);
|
||
|
if (rx.notFull) begin
|
||
|
rx.enq(shift_in);
|
||
|
rx_state <= WaitIdle;
|
||
|
end
|
||
|
else
|
||
|
rx_state <= Cork;
|
||
|
endrule
|
||
|
|
||
|
(* fire_when_enabled *)
|
||
|
rule rx_cork (rx_state == Cork);
|
||
|
rx.enq(shift_in);
|
||
|
rx_state <= WaitIdle;
|
||
|
endrule
|
||
|
|
||
|
interface UART_RX_PHY phy;
|
||
|
method rx_in = rx_sync._write;
|
||
|
method Bool stop_sending();
|
||
|
// Signal is active low, so 1 == "stop sending"
|
||
|
return rx_state == Cork;
|
||
|
endmethod
|
||
|
endinterface
|
||
|
|
||
|
interface receive = toGet(rx);
|
||
|
endmodule
|
||
|
|
||
|
typedef enum {
|
||
|
Idle,
|
||
|
Ready,
|
||
|
Send
|
||
|
} TXState deriving (Bits, Eq);
|
||
|
|
||
|
module mkUARTTransmitter(Integer clock_frequency, Integer uart_bitrate, UART_TX ifc);
|
||
|
Reg#(bit) cts_sync <- mkPinSync(0);
|
||
|
let cts_in <- mkGlitchFilter(3, 0);
|
||
|
mkConnection(toGet(asReg(cts_sync)), toPut(asReg(cts_in)));
|
||
|
|
||
|
Reg#(TXState) tx_state <- mkReg(Idle);
|
||
|
Strobe bit_strobe <- mkStrobe(clock_frequency, uart_bitrate);
|
||
|
Reg#(UInt#(4)) cnt <- mkReg(0);
|
||
|
Reg#(Bit#(9)) shift_out <- mkReg(9'h1FF);
|
||
|
FIFOF#(Bit#(8)) tx <- mkPipelineFIFOF();
|
||
|
|
||
|
(* fire_when_enabled *)
|
||
|
rule tx_idle (tx_state == Idle && tx.notEmpty);
|
||
|
shift_out <= {tx.first, 0};
|
||
|
tx.deq();
|
||
|
tx_state <= Ready;
|
||
|
bit_strobe.reset();
|
||
|
endrule
|
||
|
|
||
|
(* no_implicit_conditions, fire_when_enabled *)
|
||
|
rule rx_ready (tx_state == Ready && bit_strobe && cts_in == 1);
|
||
|
tx_state <= Send;
|
||
|
cnt <= 0;
|
||
|
endrule
|
||
|
|
||
|
(* no_implicit_conditions, fire_when_enabled *)
|
||
|
rule tx_send (tx_state == Send && bit_strobe);
|
||
|
shift_out <= {1'b1, shift_out[8:1]};
|
||
|
cnt <= cnt+1;
|
||
|
if (cnt == 9)
|
||
|
tx_state <= Idle;
|
||
|
endrule
|
||
|
|
||
|
interface UART_TX_PHY phy;
|
||
|
method bit tx_out();
|
||
|
if (tx_state == Send)
|
||
|
return shift_out[0];
|
||
|
else
|
||
|
return 1'b1;
|
||
|
endmethod
|
||
|
method Action can_send(b);
|
||
|
cts_sync <= pack(b);
|
||
|
endmethod
|
||
|
endinterface
|
||
|
|
||
|
interface Put send = toPut(tx);
|
||
|
endmodule
|
||
|
|
||
|
module mkUART(Integer clock_frequency, Integer uart_bitrate, UART ifc);
|
||
|
let _rx <- mkUARTReceiver(clock_frequency, uart_bitrate);
|
||
|
let _tx <- mkUARTTransmitter(clock_frequency, uart_bitrate);
|
||
|
|
||
|
interface UART_PHY phy;
|
||
|
method rx_in = _rx.phy.rx_in;
|
||
|
method tx_out = _tx.phy.tx_out;
|
||
|
method stop_sending = _rx.phy.stop_sending;
|
||
|
method can_send = _tx.phy.can_send;
|
||
|
endinterface
|
||
|
interface send = _tx.send;
|
||
|
interface receive = _rx.receive;
|
||
|
endmodule
|
||
|
|
||
|
typeclass FlowControlled#(type ifc);
|
||
|
module disableFlowControl(ifc i, Empty ret);
|
||
|
endtypeclass
|
||
|
|
||
|
instance FlowControlled#(UART_RX_PHY);
|
||
|
module disableFlowControl(UART_RX_PHY phy, Empty ifc);
|
||
|
endmodule
|
||
|
endinstance
|
||
|
|
||
|
instance FlowControlled#(UART_TX_PHY);
|
||
|
module disableFlowControl(UART_TX_PHY phy, Empty ifc);
|
||
|
(* no_implicit_conditions,fire_when_enabled *)
|
||
|
rule always_send;
|
||
|
phy.can_send(True);
|
||
|
endrule
|
||
|
endmodule
|
||
|
endinstance
|
||
|
|
||
|
instance FlowControlled#(UART_PHY);
|
||
|
module disableFlowControl(UART_PHY phy, Empty ifc);
|
||
|
(* no_implicit_conditions,fire_when_enabled *)
|
||
|
rule always_send;
|
||
|
phy.can_send(True);
|
||
|
endrule
|
||
|
endmodule
|
||
|
endinstance
|
||
|
|
||
|
instance FlowControlled#(UART_RX);
|
||
|
module disableFlowControl(UART_RX rx, Empty ifc);
|
||
|
disableFlowControl(rx.phy);
|
||
|
endmodule
|
||
|
endinstance
|
||
|
|
||
|
instance FlowControlled#(UART_TX);
|
||
|
module disableFlowControl(UART_TX tx, Empty ifc);
|
||
|
disableFlowControl(tx.phy);
|
||
|
endmodule
|
||
|
endinstance
|
||
|
|
||
|
instance FlowControlled#(UART);
|
||
|
module disableFlowControl(UART uart, Empty ifc);
|
||
|
disableFlowControl(uart.phy);
|
||
|
endmodule
|
||
|
endinstance
|
||
|
|
||
|
endpackage
|