2 Copyright (c) 2013-2017, IIT Madras
5 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
7 * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
8 * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
9 * Neither the name of IIT Madras nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
11 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
12 ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
14 * Copyright (c) 2013 Simon W. Moore
15 * All rights reserved.
17 * This software was developed by SRI International and the University of
18 * Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-10-C-0237
19 * ("CTSRD"), as part of the DARPA CRASH research programme.
21 * @BERI_LICENSE_HEADER_START@
23 * Licensed to BERI Open Systems C.I.C. (BERI) under one or more contributor
24 * license agreements. See the NOTICE file distributed with this work for
25 * additional information regarding copyright ownership. BERI licenses this
26 * file to you under the BERI Hardware-Software License, Version 1.0 (the
27 * "License"); you may not use this file except in compliance with the
28 * License. You may obtain a copy of the License at:
30 * http://www.beri-open-systems.org/legal/license-1-0.txt
32 * Unless required by applicable law or agreed to in writing, Work distributed
33 * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
34 * CONDITIONS OF ANY KIND, either express or implied. See the License for the
35 * specific language governing permissions and limitations under the License.
37 * @BERI_LICENSE_HEADER_END@
39 ******************************************************************************
42 * Simon Moore, July 2013
44 * This Bluespec module implements a 16650 style UART for RS232 serial
47 * The following registers exist at 32-bit boundaries accessible in little
50 * Offset Name Read/Write Description
51 * 0 UART_DATA RW write to transmit, read to receive
52 * 1 UART_INT_ENABLE RW interrupt enable
53 * 2 UART_INT_ID R interrupt identification
54 * 2 UART_FIFO_CTRL W FIFO control
55 * 3 UART_LINE_CTRL RW line control
56 * 4 UART_MODEM_CTRL W modem control
57 * 5 UART_LINE_STATUS R line status
58 * 6 UART_MODEM_STATUS R modem status
59 * 7 UART_SCRATCH RW scratch register
60 ******************************************************************************/
62 //Modifications - The Avalon bus has been removed and AXI-4 Lite Bus support has been added
71 import ClientServer::*;
72 import defined_types::*;
73 import AXI4_Lite_Types::*;
74 import AXI4_Lite_Fabric::*;
76 `include "instance_defines.bsv"
78 // depth of transmit and receive FIFOs
79 typedef 16 Tx_FIFO_depth;
80 typedef 16 Rx_FIFO_depth;
82 // enumerate addresses corresponding to device registers
85 UART_ADDR_INT_ENABLE=1,
86 UART_ADDR_INT_ID_FIFO_CTRL=2, // read=INT_ID, write=FIFO_CTRL
87 UART_ADDR_LINE_CTRL=3,
88 UART_ADDR_MODEM_CTRL=4,
89 UART_ADDR_LINE_STATUS=5,
90 UART_ADDR_MODEM_STATUS=6,
92 } UART_ADDR_T deriving (Bits, Eq, FShow);
94 // interrupt enable register bits
96 Bool uart_IE_MS; // Modem status interrupt
97 Bool uart_IE_RLS; // Receiver line status interrupt
98 Bool uart_IE_THRE; // Transmitter holding register empty interrupt
99 Bool uart_IE_RDA; // Recived data available interrupt
100 } UART_IE_T deriving (Bits, Eq, FShow);
102 // interrupt identification values
104 UART_II_MS = 4'b0000, // modem status
105 UART_II_NO_INT = 4'b0001, // no interrupt pending
106 UART_II_THRE = 4'b0010, // transmitter holding register empty
107 UART_II_RDA = 4'b0100, // receiver data available
108 UART_II_RLS = 4'b0110, // receiver line status
109 UART_II_TI = 4'b1100 // timeout indication
110 } UART_II_T deriving (Bits, Eq, FShow);
112 // line control register bits
114 Bit#(1) uart_LC_DL; // divisor latch access bit
115 Bit#(1) uart_LC_BC; // break control
116 Bit#(1) uart_LC_SP; // stick parity
117 Bit#(1) uart_LC_EP; // even parity
118 Bit#(1) uart_LC_PE; // parity enables
119 Bit#(1) uart_LC_SB; // stop bits
120 Bit#(2) uart_LC_BITS; // bits in character
121 } UART_LC_T deriving (Bits, Eq, FShow);
123 // modem control register bits
125 bit uart_MC_LOOPBACK;
130 } UART_MC_T deriving (Bits, Eq, FShow);
132 // line status register bits
134 Bool uart_LS_EI; // error indicator
135 Bool uart_LS_TW; // transmitter empty indicator
136 Bool uart_LS_TFE; // transmitter FIFO is empty
137 Bool uart_LS_BI; // break interrupt
138 Bool uart_LS_FE; // framing error
139 Bool uart_LS_PE; // parity error
140 Bool uart_LS_OE; // overrun error
141 Bool uart_LS_DR; // data ready
142 } UART_LS_T deriving (Bits, Eq, FShow);
144 // modem status register bits
146 bit uart_MS_CDCD; // complement signals
150 bit uart_MS_DDCD; // delta signals
154 } UART_MS_T deriving (Bits, Eq, FShow);
156 // data from receiver
162 } RX_DATA_T deriving (Bits, Eq);
164 // transmitter states
166 STX_idle, STX_pop_byte, STX_send_start, STX_send_byte, STX_send_parity, STX_send_stop
167 } TX_state_T deriving (Bits, Eq, FShow);
171 SRX_idle, SRX_rec_start, SRX_rec_bit, SRX_rec_parity, SRX_rec_stop,
172 SRX_check_parity, SRX_rec_prepare, SRX_end_bit, SRX_wait1,
173 SRX_ca_lc_parity, SRX_push } RX_state_T deriving (Bits, Eq, FShow);
176 (* always_ready, always_enabled *)
177 interface RS232_PHY_Ifc;
178 (* always_ready, always_enabled *) method Action modem_input(bit srx, bit cts, bit dsr, bit ri, bit dcd);
179 method bit modem_output_stx;
180 method bit modem_output_rts;
181 method bit modem_output_dtr;
185 interface Uart16550_AXI4_Lite_Ifc;
186 interface RS232_PHY_Ifc coe_rs232;
187 interface AXI4_Lite_Slave_IFC#(`PADDR,`Reg_width,`USERSPACE) slave_axi_uart;
188 (* always_ready, always_enabled *) method bit irq;
193 reset_prefix = "csi_clockreset_reset_n",
194 clock_prefix = "csi_clockreset_clk" *)
195 module mkUart16550#(Clock core_clock, Reset core_reset)(Uart16550_AXI4_Lite_Ifc);
196 AXI4_Lite_Slave_Xactor_IFC #(`PADDR,`Reg_width,`USERSPACE) s_xactor <- mkAXI4_Lite_Slave_Xactor(clocked_by core_clock, reset_by core_reset);
197 UART_transmitter_ifc uart_tx <- mkUART_transmitter;
198 UART_receiver_ifc uart_rx <- mkUART_receiver;
200 // TODO: FIXME: use Tx_FIFO_depth and Rx_FIFO_depth rather than 16?
201 // TX should only have a 1 element FIFO
202 // FIFOCountIfc#(Bit#(8), 16) tx_fifo <- mkGFIFOCount(True, False, True);
203 FIFOF#(Bit#(8)) tx_fifo <- mkGFIFOF1(True, False);
204 FIFOCountIfc#(RX_DATA_T, 16) rx_fifo <- mkGFIFOCount(True, True, True);
205 PulseWire tx_fifo_clear_pw <- mkPulseWire;
206 PulseWire rx_fifo_clear_pw <- mkPulseWire;
207 // add some bypass wires to hack around scheduling loop
208 Wire#(Bool) rx_fifo_full <- mkBypassWire;
209 Wire#(Bool) rx_fifo_empty <- mkBypassWire;
210 Wire#(Bool) tx_fifo_empty <- mkBypassWire;
211 // provide first item of rx_fifo if there is one, otherwise a default
212 Wire#(RX_DATA_T) rx_fifo_first <- mkBypassWire;
214 PulseWire count_error_up <- mkPulseWire;
215 PulseWire count_error_down <- mkPulseWire;
216 PulseWire count_error_clear <- mkPulseWire;
217 Reg#(UInt#(TAdd#(Rx_FIFO_depth,1)))
218 count_error <- mkReg(0);
220 Reg#(Bit#(2)) fcr <- mkReg(2'b11); // upper 2 bits of FIFO control register (rest not stored)
221 Reg#(UART_IE_T) ier <- mkReg(unpack(0)); // interrupt enable register bits (disable after reset)
222 Reg#(UART_LC_T) lcr <- mkReg(unpack('b00000011)); // line control register (default 8n1 format)
223 Reg#(UART_MC_T) mcr <- mkReg(unpack(0)); // modem control register
224 Wire#(UART_MC_T) mc_bypass <- mkBypassWire;
225 Reg#(UART_LS_T) lsr <- mkReg(unpack(0)); // line status register
226 Reg#(UART_MS_T) msr <- mkReg(unpack(0)); // modem status register
227 Reg#(Bit#(8)) scratch <- mkReg(unpack(0)); // scratch register
229 Wire#(Bool) loopback <- mkBypassWire; // loopback mode (msr[4])
231 Reg#(Bit#(8)) dl1r <- mkReg(0); // divisor 1 register
232 Reg#(Bit#(8)) dl2r <- mkReg(0); // divisor 2 register
233 Reg#(Bit#(16)) dlc <- mkReg(0); // divisor counter
234 Reg#(Bit#(16)) dl <- mkReg(0); // divisor counter bound
235 Reg#(Bool) enable <- mkReg(False);
236 Wire#(Maybe#(Bit#(16)))
237 dl_update <- mkDWire(tagged Invalid);
239 PulseWire interrupt_pw <- mkPulseWireOR;
240 RS_ifc rls_int <- mkRS;
241 RS_ifc rda_int <- mkRS;
242 RS_ifc thre_int <- mkRS;
243 RS_ifc ms_int <- mkRS;
244 RS_ifc ti_int <- mkRS;
246 // synchroniser registers for input pins
247 Reg#(bit) pin_srx_sync <- mkReg(0);
248 Reg#(bit) pin_cts_sync <- mkReg(0);
249 Reg#(bit) pin_dsr_sync <- mkReg(0);
250 Reg#(bit) pin_ri_sync <- mkReg(0);
251 Reg#(bit) pin_dcd_sync <- mkReg(0);
253 // registers for stable input pin values pre loopback check
254 Reg#(bit) pin_srx_c <- mkReg(0);
255 Reg#(bit) pin_cts_c <- mkReg(0);
256 Reg#(bit) pin_dsr_c <- mkReg(0);
257 Reg#(bit) pin_ri_c <- mkReg(0);
258 Reg#(bit) pin_dcd_c <- mkReg(0);
260 // registers for stable input pin values
261 Reg#(bit) pin_srx <- mkReg(0);
262 Reg#(bit) pin_cts <- mkReg(0);
263 Reg#(bit) pin_dsr <- mkReg(0);
264 Reg#(bit) pin_ri <- mkReg(0);
265 Reg#(bit) pin_dcd <- mkReg(0);
267 // previous pin values last read via MSR (modem status register)
268 Reg#(bit) prev_cts <- mkReg(0);
269 Reg#(bit) prev_dsr <- mkReg(0);
270 Reg#(bit) prev_ri <- mkReg(0);
271 Reg#(bit) prev_dcd <- mkReg(0);
272 PulseWire msr_save_pin_state <- mkPulseWire; // trigger condition to save pin state
274 // registered outputs
275 Reg#(bit) pin_stx <- mkReg(0);
276 Reg#(bit) pin_rts <- mkReg(0);
277 Reg#(bit) pin_dtr <- mkReg(0);
279 SyncFIFOIfc#(AXI4_Lite_Rd_Addr #(`PADDR,`USERSPACE)) ff_rd_addr <- mkSyncFIFOToCC(1,core_clock,core_reset);
280 SyncFIFOIfc#(AXI4_Lite_Wr_Addr #(`PADDR, `USERSPACE)) ff_wr_addr <- mkSyncFIFOToCC(1,core_clock,core_reset);
281 SyncFIFOIfc#(AXI4_Lite_Wr_Data #(`Reg_width)) ff_wr_data <- mkSyncFIFOToCC(1,core_clock,core_reset);
283 SyncFIFOIfc#(AXI4_Lite_Rd_Data #(`Reg_width,`USERSPACE)) ff_rd_resp <- mkSyncFIFOFromCC(1,core_clock);
284 SyncFIFOIfc#(AXI4_Lite_Wr_Resp #(`USERSPACE)) ff_wr_resp <- mkSyncFIFOFromCC(1,core_clock);
287 (* no_implicit_conditions *)
288 rule synchronise_input_pins; // N.B. there must be no logic between these registers
289 pin_srx_c <= pin_srx_sync;
290 pin_cts_c <= pin_cts_sync;
291 pin_dsr_c <= pin_dsr_sync;
292 pin_ri_c <= pin_ri_sync;
293 pin_dcd_c <= pin_dcd_sync;
296 rule bypass_mrc_to_avoid_scheduling_loop;
300 (* no_implicit_conditions *)
301 rule handle_loopback_mode;
305 pin_cts <= mc_bypass.uart_MC_RTS;
306 pin_dsr <= mc_bypass.uart_MC_DTR;
307 pin_ri <= mc_bypass.uart_MC_OUT1;
308 pin_dcd <= mc_bypass.uart_MC_OUT2;
312 pin_srx <= pin_srx_c;
313 pin_cts <= pin_cts_c;
314 pin_dsr <= pin_dsr_c;
316 pin_dcd <= pin_dcd_c;
320 // first changes in the pins
321 uart_MS_DCTS: pin_cts ^ prev_cts,
322 uart_MS_DDSR: pin_dsr ^ prev_dsr,
323 uart_MS_TERI: pin_ri ^ prev_ri,
324 uart_MS_DDCD: pin_dcd ^ prev_dcd,
325 // then the actual signals
326 uart_MS_CCTS: pin_cts, // TODO: allow this to be from loopback
327 uart_MS_CDSR: pin_dsr,
329 uart_MS_CDCD: pin_dcd};
331 if(msr_save_pin_state)
340 (* no_implicit_conditions *)
342 pin_rts <= mcr.uart_MC_RTS;
343 pin_dtr <= mcr.uart_MC_DTR;
346 (* no_implicit_conditions *)
347 rule loopback_mode_select;
348 loopback <= mcr.uart_MC_LOOPBACK==1;
351 (* no_implicit_conditions *)
352 rule connect_pins_rx;
353 uart_rx.input_srx(pin_srx);
355 (* no_implicit_conditions *)
356 rule connect_pins_tx;
357 pin_stx <= uart_tx.output_stx;
359 (* no_implicit_conditions *)
360 rule rx_first_item_if_any;
361 rx_fifo_first <= rx_fifo.notEmpty ? rx_fifo.first
366 framing_error: False};
369 (* no_implicit_conditions *)
370 rule interrupt_sources;
371 if(rda_int.state || rls_int.state || thre_int.state || ms_int.state || ti_int.state)
374 // receiver line status interrupt
375 // - note: also reset on read of line status
379 || rx_fifo_first.parity_error
380 || rx_fifo_first.framing_error
381 || rx_fifo_first.break_error)
384 // received data available interrupt
385 UInt#(5) trigger_level;
387 // 2'b00 handled by default case
388 2'b01 : trigger_level = 4;
389 2'b10 : trigger_level = 8;
390 2'b11 : trigger_level = 14;
391 default : trigger_level = 1;
393 // TODO: should this in fact be edge triggered on the trigger level being reached or passed?
394 if(ier.uart_IE_RDA && !rx_fifo_empty && (rx_fifo.count >= trigger_level))
399 // transmitter holding register empty interrupt
400 // if(!ier.uart_IE_THRE)
401 if(!ier.uart_IE_THRE || !tx_fifo_empty)
403 else if(tx_fifo_empty)
404 thre_int.posedge_set;
409 else if(uart_rx.timeout)
412 // modem status interrupt
413 // - note: also reset by reading modem status
416 else if({msr.uart_MS_DCTS, msr.uart_MS_DDSR, msr.uart_MS_TERI, msr.uart_MS_DDCD} != 0)
420 (* no_implicit_conditions *)
421 rule foward_lc_enable;
422 uart_tx.control(lcr, enable);
423 uart_rx.control(lcr, enable);
426 (* no_implicit_conditions *)
427 rule divisor_counter;
428 enable <= (dlc==0) && (dl>0);
429 if(isValid(dl_update))
431 let newdl = fromMaybe(?, dl_update);
434 `ifdef verbose $display("%05t: dl set to %1d", $time, newdl); `endif
437 dlc <= (dlc==0 ? dl : dlc) - 1;
440 (* no_implicit_conditions *)
441 rule forward_tx_clear(tx_fifo_clear_pw);
444 rule forward_tx(!tx_fifo_clear_pw && tx_fifo.notEmpty);
445 uart_tx.tx_char(tx_fifo.first);
452 else if(rx_fifo.notFull)
454 RX_DATA_T rx <- uart_rx.rx_char;
456 if(rx.break_error || rx.parity_error || rx.framing_error)
457 count_error_up.send();
461 (* no_implicit_conditions *)
462 rule count_rx_errors;
463 if(count_error_clear)
467 if(count_error_up && !count_error_down && (count_error<fromInteger(valueOf(Rx_FIFO_depth))))
468 count_error <= count_error+1;
469 if(!count_error_up && count_error_down && (count_error>0))
470 count_error <= count_error-1;
474 (* no_implicit_conditions *)
475 rule fifo_status_bypass_to_avoid_scheduling_loop;
476 rx_fifo_full <= !rx_fifo.notFull;
477 rx_fifo_empty <= !rx_fifo.notEmpty;
478 tx_fifo_empty <= !tx_fifo.notEmpty;
481 rule capture_read_request;
482 let req <- pop_o (s_xactor.o_rd_addr);
485 rule send_read_respone_to_bus;
486 s_xactor.i_rd_data.enq(ff_rd_resp.first);
489 rule capture_write_request;
490 let req <- pop_o (s_xactor.o_wr_addr);
491 let wr_data <- pop_o(s_xactor.o_wr_data);
493 ff_wr_data.enq(wr_data);
495 rule send_write_response;
496 s_xactor.i_wr_resp.enq(ff_wr_resp.first);
501 rule handle_axi4_read(ff_rd_addr.notEmpty);
503 Bool dlab = lcr.uart_LC_DL == 1'b1; // divisor latch enable
504 let req = ff_rd_addr.first;
506 `ifdef verbose $display("RD_ADDR %h", req.araddr); `endif
507 UART_ADDR_T addr = unpack(req.araddr[5:3]);
512 uart_LS_EI: rx_fifo_full || (count_error!=0), // error indicator
513 uart_LS_TW: tx_fifo_empty && uart_tx.tx_buf_empty, // transmitter empty
514 uart_LS_TFE: tx_fifo_empty, // transmitter FIFO empty
515 uart_LS_BI: rx_fifo_first.break_error, // break error
516 uart_LS_FE: rx_fifo_first.framing_error, // framing error
517 uart_LS_PE: rx_fifo_first.parity_error, // parity error
518 uart_LS_OE: rx_fifo_full, // overflow
519 uart_LS_DR: !rx_fifo_empty}; // data ready
524 if(rls_int.state) // highest priority interrupt - receiver line status
526 else if(rda_int.state) // second priority interrupt - received data available
528 else if(ti_int.state) // also second priority - timeout
530 else if(thre_int.state) // third priority - transmitter holding register empty
532 else if(ms_int.state) // fourth - modem status change interrupt
536 `ifdef verbose $display("addr_READ: %d",addr) ; `endif
538 UART_ADDR_DATA : if(dlab) // divisor latch enabled
540 else if(!rx_fifo_empty)
542 RX_DATA_T rx = rx_fifo.first;
544 if(rx.break_error || rx.parity_error || rx.framing_error)
545 count_error_down.send;
551 rtn_valid = False; // TODO: should this be the old value?
552 UART_ADDR_INT_ENABLE : rtn = dlab ? dl2r : zeroExtend(pack(ier));
553 UART_ADDR_INT_ID_FIFO_CTRL : rtn = {4'b1100, pack(ii)};
554 UART_ADDR_LINE_CTRL : rtn = pack(lcr);
555 UART_ADDR_MODEM_CTRL : rtn = zeroExtend(pack(mcr));
556 UART_ADDR_LINE_STATUS : begin
560 UART_ADDR_MODEM_STATUS : begin
563 msr_save_pin_state.send();
565 UART_ADDR_SCRATCH : rtn = scratch;
568 let resp = AXI4_Lite_Rd_Data {rresp : AXI4_LITE_OKAY, rdata : rtn_valid? zeroExtend(rtn) : '1, ruser: 0};
569 ff_rd_resp.enq(resp);
570 // $display ("DATA----------- %b", rtn);
571 `ifdef verbose $display("%05t: --------------------------READ--------------------------------------------",$time); `endif
574 rule handle_axi4_write(ff_wr_addr.notEmpty && ff_wr_data.notEmpty);
575 Bool dlab = lcr.uart_LC_DL == 1'b1; // divisor latch enable
577 uart_LS_EI: rx_fifo_full || (count_error!=0), // error indicator
578 uart_LS_TW: tx_fifo_empty && uart_tx.tx_buf_empty, // transmitter empty
579 uart_LS_TFE: tx_fifo_empty, // transmitter FIFO empty
580 uart_LS_BI: rx_fifo_first.break_error, // break error
581 uart_LS_FE: rx_fifo_first.framing_error, // framing error
582 uart_LS_PE: rx_fifo_first.parity_error, // parity error
583 uart_LS_OE: rx_fifo_full, // overflow
584 uart_LS_DR: !rx_fifo_empty}; // data ready
589 if(rls_int.state) // highest priority interrupt - receiver line status
591 else if(rda_int.state) // second priority interrupt - received data available
593 else if(ti_int.state) // also second priority - timeout
595 else if(thre_int.state) // third priority - transmitter holding register empty
597 else if(ms_int.state) // fourth - modem status change interrupt
602 let wr_addr = ff_wr_addr.first;
603 `ifdef verbose $display("WR_ADDR %h", wr_addr.awaddr); `endif
605 let wr_data = ff_wr_data.first;
607 `ifdef verbose $display("WR_DATA %h", wr_data.wdata); `endif
608 UART_ADDR_T addr = unpack(wr_addr.awaddr[5:3]);
609 Bit#(8) d = truncate(pack(wr_data.wdata));
612 `ifdef verbose $display("addr_WRITE: %d",addr); `endif
614 UART_ADDR_DATA: if(dlab) // divisor latch enabled
617 dl_update <= tagged Valid ({dl2r,d});
619 else if(tx_fifo.notFull)
621 tx_fifo.enq(unpack(d));
624 UART_ADDR_INT_ENABLE: if(dlab)
627 ier <= unpack(truncate(d));
628 UART_ADDR_INT_ID_FIFO_CTRL: begin
632 rx_fifo_clear_pw.send;
633 count_error_clear.send;
636 tx_fifo_clear_pw.send;
638 UART_ADDR_LINE_CTRL : lcr <= unpack(truncate(pack(wr_data.wdata)));
639 UART_ADDR_MODEM_CTRL : mcr <= unpack(truncate(pack(wr_data.wdata)));
640 UART_ADDR_LINE_STATUS : begin /* no write */ end
641 UART_ADDR_MODEM_STATUS : begin /* no write */ end
642 UART_ADDR_SCRATCH : begin scratch <= d; `ifdef verbose $display("scratch : %h",d); `endif end
644 let resp = AXI4_Lite_Wr_Resp {bresp: AXI4_LITE_OKAY, buser: 0};
645 ff_wr_resp.enq(resp);
646 // $display ("DATA WRITE----------- %b", wr_data.wdata);
647 // $display ("DATA Adress----------- %d", addr);
648 `ifdef verbose $display("%05t: ----------------------------WRITE------------------------------------------",$time); `endif
652 $display("%05t: tx bit = %b", $time, pin_stx);
655 interface RS232_PHY_Ifc coe_rs232;
656 method Action modem_input(bit srx, bit cts, bit dsr, bit ri, bit dcd);
657 pin_srx_sync <= srx; // RX Input
658 pin_cts_sync <= cts; // CTS Input
659 pin_dsr_sync <= dsr; // Data Set Ready indicating that MODEM is ready to establish the communication
660 pin_ri_sync <= ri; // Ring Indicator indicate that a telephone ringing signal has been recieved by the MODEM
661 pin_dcd_sync <= dcd; // Data carrier detect
663 method bit modem_output_stx = pin_stx; // Tx output
664 method bit modem_output_rts = pin_rts; // RTS output
665 method bit modem_output_dtr = pin_dtr; // Data Terminal Ready output
668 interface slave_axi_uart = s_xactor.axi_side;
671 return interrupt_pw ? 1'b1 : 1'b0;
679 //////////////////////////////////////////////////////////////////////////////
682 interface UART_transmitter_ifc;
683 method Action tx_char(Bit#(8) c);
684 (* always_ready, always_enabled *)
685 method Bool tx_buf_empty;
686 (* always_ready, always_enabled *)
687 method Action control(UART_LC_T lc_in, Bool enable_in);
688 (* always_ready, always_enabled *)
689 method bit output_stx;
693 module mkUART_transmitter(UART_transmitter_ifc);
695 FIFOF#(Bit#(8)) tx_fifo <- mkLFIFOF;
696 Wire#(Bool) tx_fifo_empty <- mkBypassWire;
697 Reg#(bit) bit_out <- mkReg(0);
698 Reg#(bit) parity_xor <- mkReg(0);
699 Reg#(bit) stx_o_tmp <- mkReg(1); // rename output bit? our use bit_out directly?
700 Reg#(TX_state_T) tstate <- mkReg(STX_idle);
701 Reg#(TX_state_T) last_tstate <- mkReg(STX_idle);
702 Reg#(UInt#(5)) counter <- mkReg(0);
703 Reg#(UInt#(3)) bit_counter <- mkReg(0);
704 Reg#(Bit#(7)) shift_out <- mkReg(0);
705 Wire#(UART_LC_T) lc <- mkBypassWire;
706 Wire#(Bool) enable <- mkBypassWire;
708 rule monitor_state_for_debug(last_tstate != tstate);
710 `ifdef verbose $write("%05t: UART TX state change ", $time); `endif
711 `ifdef verbose $write(fshow(last_tstate)); `endif
712 `ifdef verbose $write(" -> "); `endif
713 `ifdef verbose $display(fshow(tstate)); `endif
715 last_tstate <= tstate;
718 // rule to decouple rule dependency on tx_fifo.notEmpty
719 (* no_implicit_conditions *)
720 rule forward_tx_fifo_empty;
721 tx_fifo_empty <= !tx_fifo.notEmpty;
724 rule idle(enable && (tstate==STX_idle));
725 tstate <= STX_pop_byte; // move directly to pop_byte since it will block if the tx_fifo is empty
729 rule pop_byte(enable && (tstate==STX_pop_byte));
730 case(lc.uart_LC_BITS) // number of bits in a word
733 parity_xor <= ^tx_fifo.first[4:0];
737 parity_xor <= ^tx_fifo.first[5:0];
741 parity_xor <= ^tx_fifo.first[6:0];
745 parity_xor <= ^tx_fifo.first[7:0];
748 shift_out[6:0] <= tx_fifo.first[7:1];
749 bit_out <= tx_fifo.first[0];
750 tstate <= STX_send_start;
753 rule send_start(enable && (tstate==STX_send_start));
760 tstate <= STX_send_byte;
763 counter <= counter-1;
767 rule send_byte(enable && (tstate==STX_send_byte));
774 bit_counter <= bit_counter-1;
775 shift_out <= {1'b0,shift_out[6:1]};
776 bit_out <= shift_out[0];
779 if(lc.uart_LC_PE == 0) // no partity bit
780 tstate <= STX_send_stop;
783 case({lc.uart_LC_EP, lc.uart_LC_SP})
784 2'b00: bit_out <= ~parity_xor;
786 2'b10: bit_out <= parity_xor;
789 tstate <= STX_send_parity;
794 counter <= counter-1;
795 stx_o_tmp <= bit_out;
798 rule send_parity(enable && (tstate==STX_send_parity));
804 tstate <= STX_send_stop;
807 counter <= counter-1;
808 stx_o_tmp <= bit_out;
812 rule send_stop(enable && (tstate==STX_send_stop));
814 counter <= lc.uart_LC_SB==0 ? 5'b01101 : // 1 stop bit
815 lc.uart_LC_BITS==0 ? 5'b10101 : // 1.5 stop bits
816 5'b11101; // 2 stop bits
824 counter <= counter-1;
829 method Action tx_char(Bit#(8) c);
833 method Bool tx_buf_empty = tx_fifo_empty;
835 method Action control(UART_LC_T lc_in, Bool enable_in);
840 method bit output_stx = lc.uart_LC_BC==1 ? 0 : stx_o_tmp; // handle break condition
845 //////////////////////////////////////////////////////////////////////////////
848 interface UART_receiver_ifc;
849 method ActionValue#(RX_DATA_T) rx_char();
850 (* always_ready, always_enabled *)
851 method Bool timeout();
852 (* always_ready, always_enabled *)
853 method Action control(UART_LC_T lc_in, Bool enable_in);
854 (* always_ready, always_enabled *)
855 method Action input_srx(bit rx);
859 module mkUART_receiver(UART_receiver_ifc);
861 FIFOF#(RX_DATA_T) rx_fifo <- mkLFIFOF;
862 Reg#(bit) rx_stable <- mkReg(1);
863 Wire#(UART_LC_T) lc <- mkBypassWire;
864 Wire#(Bool) enable <- mkBypassWire;
865 Reg#(RX_state_T) rstate <- mkReg(SRX_idle);
866 Reg#(RX_state_T) last_rstate <- mkReg(SRX_idle);
867 Reg#(UInt#(4)) rcounter <- mkReg(0);
868 Reg#(UInt#(3)) rbit_counter <- mkReg(0);
869 Reg#(Bit#(8)) rshift <- mkReg(0);
870 Reg#(bit) rparity <- mkReg(0);
871 Reg#(bit) rparity_error <- mkReg(0);
872 Reg#(bit) rframing_error <- mkReg(0);
873 Reg#(bit) rparity_xor <- mkReg(0);
874 Reg#(UInt#(8)) counter_b <- mkReg(159);
875 Reg#(UInt#(10)) counter_t <- mkReg(511);
876 PulseWire counter_t_preset <- mkPulseWireOR;
878 Bool break_error = counter_b==0;
880 rule monitor_state_for_debug(last_rstate != rstate);
882 `ifdef verbose $write("%05t: UART RX state change ", $time); `endif
883 `ifdef verbose $write(fshow(last_rstate)); `endif
884 `ifdef verbose $write(" -> "); `endif
885 `ifdef verbose $display(fshow(rstate)); `endif
887 last_rstate <= rstate;
890 (* no_implicit_conditions *)
891 rule receive_status_counters;
893 case ({lc.uart_LC_PE, lc.uart_LC_SB, lc.uart_LC_BITS})
894 4'b0000: toc_value = 447; // 7 bits
895 4'b0100: toc_value = 479; // 7.5 bits
897 4'b1000: toc_value = 511; // 8 bits
898 4'b1100: toc_value = 543; // 8.5 bits
901 4'b1001: toc_value = 575; // 9 bits
905 4'b1101: toc_value = 639; // 10 bits
908 4'b1110: toc_value = 703; // 11 bits
909 4'b1111: toc_value = 767; // 12 bits
910 default: toc_value = 511; // 8 bits
913 UInt#(8) brc_value = truncate(toc_value>>2); // break counter value
916 counter_b <= brc_value;
917 else if((counter_b!=0) && enable)
918 counter_b <= counter_b-1;
921 counter_t <= toc_value;
922 else if(enable && (counter_t!=0))
923 counter_t <= counter_t - 1;
926 // helper rule to decouple firing dependancies
927 rule couter_t_preset_on_fifo_empty(!rx_fifo.notEmpty);
928 counter_t_preset.send();
931 (* no_implicit_conditions *)
932 rule idle(enable && (rstate==SRX_idle));
934 if((rx_stable==0) && !break_error)
935 rstate <= SRX_rec_start;
938 rule rec_start(enable && (rstate==SRX_rec_start));
940 if(rx_stable==1) // no start bit
943 rstate <= SRX_rec_prepare;
944 rcounter <= rcounter-1;
947 rule rec_prepare(enable && (rstate==SRX_rec_prepare));
948 rbit_counter <= unpack(zeroExtend(lc.uart_LC_BITS) + 4);
951 rstate <= SRX_rec_bit;
956 rcounter <= rcounter-1;
959 rule rec_bit(enable && (rstate==SRX_rec_bit));
961 rstate <= SRX_end_bit;
962 if(rcounter==7) // read the bit
963 case(lc.uart_LC_BITS) // number of bits in a word
964 0: rshift[4:0] <= {rx_stable, rshift[4:1]};
965 1: rshift[5:0] <= {rx_stable, rshift[5:1]};
966 2: rshift[6:0] <= {rx_stable, rshift[6:1]};
967 3: rshift[7:0] <= {rx_stable, rshift[7:1]};
969 rcounter <= rcounter-1;
972 rule end_bit(enable && (rstate==SRX_end_bit));
973 if(rbit_counter==0) // no more bits in the word
975 rstate <= (lc.uart_LC_PE==1) ? SRX_rec_parity : SRX_rec_stop;
979 rstate <= SRX_rec_bit;
980 rbit_counter <= rbit_counter-1;
981 rcounter <= rcounter-1;
984 rule rec_parity(enable && (rstate==SRX_rec_parity));
985 if(rcounter == 7) // read parity
987 rparity <= rx_stable;
988 rstate <= SRX_ca_lc_parity;
990 rcounter <= rcounter-1;
991 //$display("%05t rx bit = %d", $time, rx_stable);
995 $display("%05t: rx bit = %d", $time, rx_stable);
998 rule calc_parity(enable && (rstate==SRX_ca_lc_parity));
999 rparity_xor <= ^{rshift, rparity};
1000 rstate <= SRX_check_parity;
1001 rcounter <= rcounter-1;
1004 rule check_parity(enable && (rstate==SRX_check_parity));
1005 case({lc.uart_LC_EP, lc.uart_LC_SP})
1006 2'b00: rparity_error <= ~rparity_xor;
1007 2'b01: rparity_error <= ~rparity;
1008 2'b10: rparity_error <= rparity_xor;
1009 2'b11: rparity_error <= rparity;
1011 rcounter <= rcounter-1;
1012 rstate <= SRX_wait1;
1015 rule wait1(enable && (rstate==SRX_wait1));
1018 rcounter <= 4'b1110;
1019 rstate <= SRX_rec_stop;
1022 rcounter <= rcounter-1;
1025 rule rec_stop(enable && (rstate==SRX_rec_stop));
1026 if(rcounter==7) // read the stop bit
1028 rframing_error <= ~rx_stable; // no framing error if stop bit = 1
1031 rcounter <= rcounter-1;
1032 `ifdef verbose $display("%05t: rx bit = %d", $time, rx_stable); `endif
1035 rule push(enable && (rstate==SRX_push));
1036 if((rx_stable==1) || break_error)
1045 framing_error: False
1053 parity_error: rparity_error==1,
1054 framing_error: rframing_error==1
1057 counter_t_preset.send; // preset counter_t on an enq
1058 //$display("%05t: rx bit = %d", $time, rx_stable);
1062 method ActionValue#(RX_DATA_T) rx_char();
1063 counter_t_preset.send; // preset counter_t on a deq
1065 return rx_fifo.first;
1067 method Bool timeout() = counter_t==0;
1068 method Action control(UART_LC_T lc_in, Bool enable_in);
1070 enable <= enable_in;
1072 method Action input_srx(bit rx);
1078 //////////////////////////////////////////////////////////////////////////////
1079 // clocked RS (reset/set) flip-flow with reset dominating and edge triggering set
1082 (* always_ready, always_enabled *)
1085 method Action reset;
1086 method Action enable(Bool en);
1091 module mkRS(RS_ifc);
1092 PulseWire s <- mkPulseWire;
1093 PulseWire r <- mkPulseWireOR;
1094 Wire#(Bool) e <- mkBypassWire;
1095 Wire#(Bool) q_next <- mkBypassWire;
1096 Reg#(Bool) q <- mkReg(False);
1097 Reg#(Bool) s_prev <- mkReg(False);
1099 (* no_implicit_conditions *)
1100 rule handle_state_update;
1101 Bool s_rise = s && !s_prev;
1102 q_next <= e && !r && (s_rise || q);
1107 method Action set; s.send(); endmethod
1108 method Action reset; r.send(); endmethod
1109 method Bool state = q_next;
1110 method Action enable(Bool en);
1118 (* always_ready, always_enabled *)
1121 method Action reset;
1122 method Action posedge_set;
1123 method Action posedge_reset;
1127 module mkRS(RS_ifc);
1128 PulseWire s <- mkPulseWireOR;
1129 PulseWire r <- mkPulseWireOR;
1130 PulseWire edge_s <- mkPulseWireOR;
1131 PulseWire edge_r <- mkPulseWireOR;
1133 Reg#(Bool) q <- mkReg(False);
1134 Reg#(Bool) s_prev <- mkReg(False);
1135 Reg#(Bool) r_prev <- mkReg(False);
1138 (* no_implicit_conditions *)
1139 rule handle_edges_history;
1144 (* no_implicit_conditions *)
1145 rule handle_edges_set;
1146 if(edge_s && !s_prev) s.send;
1147 if(edge_r && !r_prev) r.send;
1150 (* no_implicit_conditions *)
1151 rule handle_state_update;
1152 q <= !r && (q || s);
1155 method Action set; s.send(); endmethod
1156 method Action reset; r.send(); endmethod
1157 method Action posedge_set; edge_s.send(); endmethod
1158 method Action posedge_reset; edge_r.send(); endmethod
1159 method Bool state = q;