Update uartPC16550D.sv

Program clean up
This commit is contained in:
Harshini Srinath 2023-06-15 10:20:29 -07:00 committed by GitHub
parent ae165b35f9
commit 53ad51ae54
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -45,7 +45,7 @@ module uartPC16550D #(parameter UART_PRESCALE, QEMU) (
output logic INTR, TXRDYb, RXRDYb, // interrupt and ready lines
// Clocks
output logic BAUDOUTb, // active low baud clock
input logic RCLK, // usually BAUDOUTb tied to RCLK externally
input logic RCLK, // usually BAUDOUTb tied to RCLK externally
// E1A Driver
input logic SIN, DSRb, DCDb, CTSb, RIb, // UART external serial and flow-control inputs
output logic SOUT, RTSb, DTRb, OUT1b, OUT2b // UART external serial and flow-control outputs
@ -71,9 +71,9 @@ module uartPC16550D #(parameter UART_PRESCALE, QEMU) (
logic DLAB; // Divisor Latch Access Bit (LCR bit 7)
// Baud and rx/tx timing
logic baudpulse, txbaudpulse, rxbaudpulse; // high one system clk cycle each baud/16 period
logic [16+UART_PRESCALE-1:0] baudcount;
logic [3:0] rxoversampledcnt, txoversampledcnt; // count oversampled-by-16
logic baudpulse, txbaudpulse, rxbaudpulse; // high one system clk cycle each baud/16 period
logic [16+UART_PRESCALE-1:0] baudcount;
logic [3:0] rxoversampledcnt, txoversampledcnt; // count oversampled-by-16
logic [3:0] rxbitsreceived, txbitssent;
statetype rxstate, txstate;
@ -122,6 +122,7 @@ module uartPC16550D #(parameter UART_PRESCALE, QEMU) (
///////////////////////////////////////////
// Input synchronization: 2-stage synchronizer
///////////////////////////////////////////
always_ff @(posedge PCLK) begin
{SINd, DSRbd, DCDbd, CTSbd, RIbd} <= #1 {SIN, DSRb, DCDb, CTSb, RIb};
{SINsync, DSRbsync, DCDbsync, CTSbsync, RIbsync} <= #1 loop ? {SOUTbit, ~MCR[0], ~MCR[3], ~MCR[1], ~MCR[2]} :
@ -132,6 +133,7 @@ module uartPC16550D #(parameter UART_PRESCALE, QEMU) (
///////////////////////////////////////////
// Register interface (Table 1, note some are read only and some write only)
///////////////////////////////////////////
always_ff @(posedge PCLK, negedge PRESETn)
if (~PRESETn) begin // Table 3 Reset Configuration
IER <= #1 4'b0;
@ -162,13 +164,13 @@ module uartPC16550D #(parameter UART_PRESCALE, QEMU) (
if (~MEMWb & (A == 3'b101))
LSR[6:1] <= #1 Din[6:1]; // recommended only for test, see 8.6.3
else begin
LSR[0] <= #1 rxdataready; // Data ready
LSR[1] <= #1 (LSR[1] | RXBR[10]) & ~squashRXerrIP;; // overrun error
LSR[2] <= #1 (LSR[2] | RXBR[9]) & ~squashRXerrIP; // parity error
LSR[3] <= #1 (LSR[3] | RXBR[8]) & ~squashRXerrIP; // framing error
LSR[4] <= #1 (LSR[4] | rxbreak) & ~squashRXerrIP; // break indicator
LSR[5] <= #1 THRE; // THRE
LSR[6] <= #1 ~txsrfull & THRE; // TEMT
LSR[0] <= #1 rxdataready; // Data ready
LSR[1] <= #1 (LSR[1] | RXBR[10]) & ~squashRXerrIP;; // overrun error
LSR[2] <= #1 (LSR[2] | RXBR[9]) & ~squashRXerrIP; // parity error
LSR[3] <= #1 (LSR[3] | RXBR[8]) & ~squashRXerrIP; // framing error
LSR[4] <= #1 (LSR[4] | rxbreak) & ~squashRXerrIP; // break indicator
LSR[5] <= #1 THRE; // THRE
LSR[6] <= #1 ~txsrfull & THRE; // TEMT
if (rxfifohaserr) LSR[7] <= #1 1; // any bits in FIFO have error
end
@ -208,6 +210,7 @@ module uartPC16550D #(parameter UART_PRESCALE, QEMU) (
///////////////////////////////////////////
// Ross Thompson: Found a bug. If the baud rate dividers DLM, and DLL are reloaded
// the baudcount is not reset to {DLM, DLL, UART_PRESCALE}
always_ff @(posedge PCLK, negedge PRESETn)
if (~PRESETn) begin
baudcount <= #1 1;
@ -233,17 +236,18 @@ module uartPC16550D #(parameter UART_PRESCALE, QEMU) (
///////////////////////////////////////////
// receive timing and control
///////////////////////////////////////////
always_ff @(posedge PCLK, negedge PRESETn)
if (~PRESETn) begin
rxoversampledcnt <= #1 0;
rxstate <= #1 UART_IDLE;
rxbitsreceived <= #1 0;
rxtimeoutcnt <= #1 0;
rxoversampledcnt <= #1 0;
rxstate <= #1 UART_IDLE;
rxbitsreceived <= #1 0;
rxtimeoutcnt <= #1 0;
end else begin
if (rxstate == UART_IDLE & ~SINsync) begin // got start bit
rxstate <= #1 UART_ACTIVE;
rxstate <= #1 UART_ACTIVE;
rxoversampledcnt <= #1 0;
rxbitsreceived <= #1 0;
rxbitsreceived <= #1 0;
if (~rxfifotimeout) rxtimeoutcnt <= #1 0; // reset timeout when new character is arriving. Jacob Pease: Only if the timeout was not already reached. p.16 PC16550D.pdf
end else if (rxbaudpulse & (rxstate == UART_ACTIVE)) begin
rxoversampledcnt <= #1 rxoversampledcnt + 1; // 16x oversampled counter
@ -260,13 +264,14 @@ module uartPC16550D #(parameter UART_PRESCALE, QEMU) (
// ***explain why
if(QEMU) assign rxcentered = rxbaudpulse & (rxoversampledcnt[1:0] == 2'b10); // implies rxstate = UART_ACTIVE
else assign rxcentered = rxbaudpulse & (rxoversampledcnt == 4'b1000); // implies rxstate = UART_ACTIVE
else assign rxcentered = rxbaudpulse & (rxoversampledcnt == 4'b1000); // implies rxstate = UART_ACTIVE
assign rxbitsexpected = 4'd1 + (4'd5 + {2'b00, LCR[1:0]}) + {3'b000, LCR[3]} + 4'd1; // start bit + data bits + (parity bit) + stop bit
///////////////////////////////////////////
// receive shift register, buffer register, FIFO
///////////////////////////////////////////
always_ff @(posedge PCLK, negedge PRESETn)
if (~PRESETn) rxshiftreg <= #1 10'b0000000001; // initialize so that there is a valid stop bit
else if (rxcentered) rxshiftreg <= #1 {rxshiftreg[8:0], SINsync}; // capture bit
@ -282,11 +287,11 @@ module uartPC16550D #(parameter UART_PRESCALE, QEMU) (
assign rxdata = LCR[3] ? rxdata9[7:0] : rxdata9[8:1]; // discard parity bit
// ERROR CONDITIONS
assign rxparity = ^rxdata;
assign rxparityerr = (rxparity ^ rxparitybit ^ ~evenparitysel) & LCR[3]; // Check even/odd parity (*** check if LCR needs to be inverted)
assign rxparity = ^rxdata;
assign rxparityerr = (rxparity ^ rxparitybit ^ ~evenparitysel) & LCR[3]; // Check even/odd parity (*** check if LCR needs to be inverted)
assign rxoverrunerr = fifoenabled ? (rxfifoentries == 15) : rxdataready; // overrun if FIFO or receive buffer register full
assign rxframingerr = ~rxstopbit; // framing error if no stop bit
assign rxbreak = rxframingerr & (rxdata9 == 9'b0); // break when 0 for start + data + parity + stop time
assign rxbreak = rxframingerr & (rxdata9 == 9'b0); // break when 0 for start + data + parity + stop time
// receive FIFO and register
always_ff @(posedge PCLK)
@ -298,7 +303,7 @@ module uartPC16550D #(parameter UART_PRESCALE, QEMU) (
end else if (rxstate == UART_DONE) begin
RXBR <= #1 {rxoverrunerr, rxparityerr, rxframingerr, rxdata}; // load recevive buffer register
if (rxoverrunerr) $warning("UART RX Overrun Err\n");
if (rxparityerr) $warning("UART RX Parity Err\n");
if (rxparityerr) $warning("UART RX Parity Err\n");
if (rxframingerr) $warning("UART RX Framing Err\n");
if (fifoenabled) begin
rxfifo[rxfifohead] <= #1 {rxoverrunerr, rxparityerr, rxframingerr, rxdata};
@ -339,14 +344,14 @@ module uartPC16550D #(parameter UART_PRESCALE, QEMU) (
else assign rxfullbitunwrapped[i] = ({1'b0,rxfifohead}==i | rxfullbitunwrapped[i-1]) & (rxfifotailunwrapped != i);
end
for (i=0; i<16; i++) begin:rx
assign RXerrbit[i] = |rxfifo[i][10:8]; // are any of the error conditions set?
assign RXerrbit[i] = |rxfifo[i][10:8]; // are any of the error conditions set?
assign rxfullbit[i] = rxfullbitunwrapped[i] | rxfullbitunwrapped[i+16];
/* if (i > 0)
assign rxfullbit[i] = ((rxfifohead==i) | rxfullbit[i-1]) & (rxfifotail != i);
else
assign rxfullbit[0] = ((rxfifohead==i) | rxfullbit[15]) & (rxfifotail != i);*/
end
assign rxfifohaserr = |(RXerrbit & rxfullbit);
assign rxfifohaserr = |(RXerrbit & rxfullbit);
// receive buffer register and ready bit
always_ff @(posedge PCLK, negedge PRESETn) // track rxrdy for DMA mode (FCR3 = FCR0 = 1)
@ -361,22 +366,23 @@ module uartPC16550D #(parameter UART_PRESCALE, QEMU) (
if (fifodmamodesel) RXRDYb = ~rxfifodmaready;
else RXRDYb = rxfifoempty;
end else begin
RBR = RXBR;
RBR = RXBR;
RXRDYb = ~rxdataready;
end
///////////////////////////////////////////
// transmit timing and control
///////////////////////////////////////////
always_ff @(posedge PCLK, negedge PRESETn)
if (~PRESETn) begin
txoversampledcnt <= #1 0;
txstate <= #1 UART_IDLE;
txbitssent <= #1 0;
txstate <= #1 UART_IDLE;
txbitssent <= #1 0;
end else if ((txstate == UART_IDLE) & txsrfull) begin // start transmitting
txstate <= #1 UART_ACTIVE;
txstate <= #1 UART_ACTIVE;
txoversampledcnt <= #1 1;
txbitssent <= #1 0;
txbitssent <= #1 0;
end else if (txbaudpulse & (txstate == UART_ACTIVE)) begin
txoversampledcnt <= #1 txoversampledcnt + 1;
if (txnextbit) begin // transmit at end of phase
@ -390,11 +396,12 @@ module uartPC16550D #(parameter UART_PRESCALE, QEMU) (
assign txbitsexpected = 4'd1 + (4'd5 + {2'b00, LCR[1:0]}) + {3'b000, LCR[3]} + 4'd1 + {3'b000, LCR[2]} - 4'd1; // start bit + data bits + (parity bit) + stop bit(s) - 1
// *** explain; is this necessary?
if (QEMU) assign txnextbit = txbaudpulse & (txoversampledcnt[1:0] == 2'b00); // implies txstate = UART_ACTIVE
else assign txnextbit = txbaudpulse & (txoversampledcnt == 4'b0000); // implies txstate = UART_ACTIVE
else assign txnextbit = txbaudpulse & (txoversampledcnt == 4'b0000); // implies txstate = UART_ACTIVE
///////////////////////////////////////////
// transmit holding register, shift register, FIFO
///////////////////////////////////////////
always_comb begin // compute value for parity and tx holding register
nexttxdata = fifoenabled ? txfifo[txfifotail] : TXHR; // pick from FIFO or holding register
case (LCR[1:0]) // compute parity from appropriate number of bits
@ -426,9 +433,9 @@ module uartPC16550D #(parameter UART_PRESCALE, QEMU) (
if (~MEMWb & A == 3'b000 & ~DLAB) begin // writing transmit holding register or fifo
if (fifoenabled) begin
txfifo[txfifohead] <= #1 Din;
txfifohead <= #1 txfifohead + 1;
txfifohead <= #1 txfifohead + 1;
end else begin
TXHR <= #1 Din;
TXHR <= #1 Din;
txhrfull <= #1 1;
end
$write("%c",Din); // for testbench
@ -436,12 +443,12 @@ module uartPC16550D #(parameter UART_PRESCALE, QEMU) (
if (txstate == UART_IDLE) begin // move data into tx shift register if available
if (fifoenabled) begin
if (~txfifoempty & ~txsrfull) begin
txsr <= #1 txdata;
txsr <= #1 txdata;
txfifotail <= #1 txfifotail+1;
txsrfull <= #1 1;
txsrfull <= #1 1;
end
end else if (txhrfull) begin
txsr <= #1 txdata;
txsr <= #1 txdata;
txhrfull <= #1 0;
txsrfull <= #1 1;
end
@ -470,13 +477,13 @@ module uartPC16550D #(parameter UART_PRESCALE, QEMU) (
HeadPointerLastMove <= 1'b0;
end
assign txfifoempty = (txfifohead == txfifotail) & ~HeadPointerLastMove;
assign txfifoempty = (txfifohead == txfifotail) & ~HeadPointerLastMove;
// verilator lint_off WIDTH
assign txfifoentries = (txfifohead >= txfifotail) ? (txfifohead-txfifotail) :
(txfifohead + 16 - txfifotail);
// verilator lint_on WIDTH
//assign txfifofull = (txfifoentries == 4'b1111);
assign txfifofull = (txfifohead == txfifotail) & HeadPointerLastMove;
//assign txfifofull = (txfifoentries == 4'b1111);
assign txfifofull = (txfifohead == txfifotail) & HeadPointerLastMove;
// transmit buffer ready bit
always_ff @(posedge PCLK, negedge PRESETn) // track txrdy for DMA mode (FCR3 = FCR0 = 1)
@ -490,11 +497,12 @@ module uartPC16550D #(parameter UART_PRESCALE, QEMU) (
// Transmitter pin
assign SOUTbit = txsr[11]; // transmit most significant bit
assign SOUT = loop ? 1 : (LCR[6] ? 0 : SOUTbit); // tied to 1 during loopback or 0 during break
assign SOUT = loop ? 1 : (LCR[6] ? 0 : SOUTbit); // tied to 1 during loopback or 0 during break
///////////////////////////////////////////
// interrupts
///////////////////////////////////////////
assign RXerr = |LSR[4:1]; // LS interrupt if any of the flags are true
assign RXerrIP = RXerr & ~squashRXerrIP; // intr squashed upon reading LSR
assign rxdataavailintr = fifoenabled ? rxfifotriggered : rxdataready;
@ -533,15 +541,15 @@ module uartPC16550D #(parameter UART_PRESCALE, QEMU) (
// modem control logic
///////////////////////////////////////////
assign loop = MCR[4];
assign loop = MCR[4];
assign DTRb = ~MCR[0] | loop; // disable modem signals in loopback mode
assign RTSb = ~MCR[1] | loop;
assign OUT1b = ~MCR[2] | loop;
assign OUT2b = ~MCR[3] | loop;
assign DLAB = LCR[7];
assign evenparitysel = LCR[4];
assign fifoenabled = FCR[0];
assign evenparitysel = LCR[4];
assign fifoenabled = FCR[0];
assign fifodmamodesel = FCR[3];
always_comb
case (FCR[7:6])