Line 35... |
Line 35... |
// ============================================================================
|
// ============================================================================
|
//
|
//
|
`define IDLE 0
|
`define IDLE 0
|
`define CNT 1
|
`define CNT 1
|
|
|
//`define UART_NO_TX_FIFO 1'b1
|
`define UART_NO_TX_FIFO 1'b1
|
|
|
module uart6551Tx(rst, clk, cyc, cs, wr, din, ack,
|
module uart6551Tx(rst, clk, cyc, cs, wr, din, ack,
|
fifoEnable, fifoClear, txBreak,
|
fifoEnable, fifoClear, txBreak,
|
frameSize, wordLength, parityCtrl, baud16x_ce,
|
frameSize, wordLength, parityCtrl, baud16x_ce,
|
cts, clear, txd, full, empty, qcnt);
|
cts, clear, txd, full, empty, qcnt);
|
Line 67... |
Line 67... |
output [3:0] qcnt; // number of characters queued
|
output [3:0] qcnt; // number of characters queued
|
|
|
reg [7:0] t1;
|
reg [7:0] t1;
|
reg [11:0] t2;
|
reg [11:0] t2;
|
reg [11:0] tx_data; // transmit data working reg (raw)
|
reg [11:0] tx_data; // transmit data working reg (raw)
|
reg state; // state machine state
|
typedef enum logic {
|
|
IDLE = 1'b0,
|
|
XMIT
|
|
} state_t;
|
|
state_t state; // state machine state
|
reg [7:0] cnt; // baud clock counter
|
reg [7:0] cnt; // baud clock counter
|
reg rd;
|
reg rd;
|
reg p1, p2; // parity bit
|
reg p1, p2; // parity bit
|
|
|
assign ack = cyc & cs;
|
assign ack = cyc & cs;
|
Line 79... |
Line 83... |
|
|
`ifdef UART_NO_TX_FIFO
|
`ifdef UART_NO_TX_FIFO
|
reg [7:0] fdo2;
|
reg [7:0] fdo2;
|
reg empty;
|
reg empty;
|
|
|
always @(posedge clk)
|
always_ff @(posedge clk)
|
if (awr) fdo2 <= {3'd0,din};
|
if (awr) fdo2 <= {3'd0,din};
|
|
|
always @(posedge clk)
|
always_ff @(posedge clk)
|
begin
|
begin
|
if (awr) empty <= 0;
|
if (awr) empty <= 0;
|
else if (rd) empty <= 1;
|
else if (rd) empty <= 1;
|
end
|
end
|
|
|
assign full = ~empty;
|
assign full = ~empty;
|
wire [7:0] fdo = fdo2;
|
wire [7:0] fdo = fdo2;
|
`else
|
`else
|
reg [7:0] fdo2;
|
reg [7:0] fdo2;
|
always @(posedge clk)
|
always_ff @(posedge clk)
|
if (awr) fdo2 <= {3'd0,din};
|
if (awr) fdo2 <= {3'd0,din};
|
// generate an empty signal for when the fifo is disabled
|
// generate an empty signal for when the fifo is disabled
|
reg fempty2;
|
reg fempty2;
|
always @(posedge clk)
|
always_ff @(posedge clk)
|
if (rst)
|
if (rst)
|
fempty2 <= 1;
|
fempty2 <= 1;
|
else begin
|
else begin
|
if (awr) fempty2 <= 0;
|
if (awr) fempty2 <= 0;
|
else if (rd) fempty2 <= 1;
|
else if (rd) fempty2 <= 1;
|
Line 130... |
Line 134... |
|
|
// mask transmit data for word length
|
// mask transmit data for word length
|
// this mask is needed for proper parity generation
|
// this mask is needed for proper parity generation
|
integer n;
|
integer n;
|
reg [7:0] mask;
|
reg [7:0] mask;
|
always @*
|
always_comb
|
for (n = 0; n < 8; n = n + 1)
|
for (n = 0; n < 8; n = n + 1)
|
mask[n] = n < wordLength ? 1'b1 : 1'b0;
|
mask[n] = n < wordLength ? 1'b1 : 1'b0;
|
|
|
always @*
|
always_comb
|
if (txBreak)
|
if (txBreak)
|
t1 <= 0;
|
t1 <= 0;
|
else
|
else
|
t1 <= fdo & mask;
|
t1 <= fdo & mask;
|
|
|
|
|
// compute parity bit
|
// compute parity bit
|
always @*
|
always_comb
|
begin
|
begin
|
case (parityCtrl)
|
case (parityCtrl)
|
3'b001: p1 <= ~^t1;// odd parity
|
3'b001: p1 <= ~^t1;// odd parity
|
3'b011: p1 <= ^t1; // even parity
|
3'b011: p1 <= ^t1; // even parity
|
3'b101: p1 <= 1; // mark bit
|
3'b101: p1 <= 1; // mark bit
|
Line 162... |
Line 166... |
|
|
always @(posedge clk)
|
always @(posedge clk)
|
if (ce) p2 <= p1;
|
if (ce) p2 <= p1;
|
*/
|
*/
|
// Insert start, parity bit and stop
|
// Insert start, parity bit and stop
|
always @*
|
always_comb
|
case(wordLength)
|
case(wordLength)
|
4'd5: t2 <= {5'b11111,p1,t1[4:0],1'b0};
|
4'd5: t2 <= {5'b11111,p1,t1[4:0],1'b0};
|
4'd6: t2 <= {4'b1111,p1,t1[5:0],1'b0};
|
4'd6: t2 <= {4'b1111,p1,t1[5:0],1'b0};
|
4'd7: t2 <= {3'b111,p1,t1[6:0],1'b0};
|
4'd7: t2 <= {3'b111,p1,t1[6:0],1'b0};
|
default: t2 <= {2'b11,p1,t1[7:0],1'b0};
|
default: t2 <= {2'b11,p1,t1[7:0],1'b0};
|
endcase
|
endcase
|
|
|
always @(posedge clk)
|
always_ff @(posedge clk)
|
if (rst)
|
if (rst)
|
state <= `IDLE;
|
state <= IDLE;
|
else begin
|
else begin
|
if (clear)
|
if (clear)
|
state <= `IDLE;
|
state <= IDLE;
|
if (baud16x_ce) begin
|
if (baud16x_ce) begin
|
case(state)
|
case(state)
|
`IDLE:
|
IDLE:
|
if ((!empty && cts)||txBreak)
|
if (((!empty && cts)||txBreak) && cnt==frameSize)
|
state <= `CNT;
|
state <= XMIT;
|
`CNT:
|
XMIT:
|
if (cnt==frameSize)
|
if (cnt==frameSize-1)
|
state <= `IDLE;
|
state <= IDLE;
|
endcase
|
endcase
|
end
|
end
|
end
|
end
|
|
|
always @(posedge clk)
|
always_ff @(posedge clk)
|
if (rst)
|
if (rst)
|
cnt <= 8'h00;
|
cnt <= 8'h00;
|
else begin
|
else begin
|
if (clear)
|
if (clear)
|
cnt <= 8'h00;
|
cnt <= 8'h00;
|
if (baud16x_ce) begin
|
if (baud16x_ce) begin
|
case(state)
|
if (cnt==frameSize)
|
`IDLE:
|
cnt <= 8'h0;
|
cnt <= 8'h00;
|
else
|
`CNT:
|
|
cnt <= cnt + 8'd1;
|
cnt <= cnt + 8'd1;
|
endcase
|
|
end
|
end
|
end
|
end
|
|
|
always @(posedge clk)
|
always_ff @(posedge clk)
|
if (rst)
|
if (rst)
|
rd <= 0;
|
rd <= 0;
|
else begin
|
else begin
|
rd <= 0;
|
rd <= 0;
|
if (clear)
|
if (clear)
|
rd <= 0;
|
rd <= 0;
|
if (baud16x_ce) begin
|
if (baud16x_ce)
|
case(state)
|
case(state)
|
`IDLE:
|
IDLE:
|
if ((!empty && cts)||txBreak)
|
if (((!empty && cts)||txBreak) && cnt==frameSize)
|
rd <= 1;
|
rd <= 1;
|
|
default: ;
|
endcase
|
endcase
|
end
|
end
|
end
|
|
|
|
always @(posedge clk)
|
always_ff @(posedge clk)
|
if (rst)
|
if (rst)
|
tx_data <= 12'hFFF;
|
tx_data <= 12'hFFF;
|
else begin
|
else begin
|
if (baud16x_ce) begin
|
if (baud16x_ce) begin
|
case(state)
|
case(state)
|
`IDLE:
|
IDLE:
|
if ((!empty && cts)||txBreak)
|
if (((!empty && cts)||txBreak) && cnt==frameSize)
|
tx_data <= t2;
|
tx_data <= t2;
|
`CNT:
|
XMIT:
|
// Shift the data out. LSB first.
|
// Shift the data out. LSB first.
|
if (cnt[3:0]==4'hF)
|
if (cnt[3:0]==4'hF)
|
tx_data <= {1'b1,tx_data[11:1]};
|
tx_data <= {1'b1,tx_data[11:1]};
|
endcase
|
endcase
|
end
|
end
|
end
|
end
|
|
|
always @(posedge clk)
|
always_ff @(posedge clk)
|
if (rst)
|
if (rst)
|
txd <= 1'b1;
|
txd <= 1'b1;
|
else
|
else
|
txd <= tx_data[0];
|
txd <= tx_data[0];
|
|
|