gary/lib/UART.bsv

244 lines
6.1 KiB
Plaintext
Raw Permalink Normal View History

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