Created
October 1, 2019 13:08
-
-
Save the6p4c/890455c23725ac515b5bf557621cb436 to your computer and use it in GitHub Desktop.
a dodgy uart, without the r
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
`default_nettype none | |
module top(input CLK, output PIN_24); | |
wire tx_buf_empty; | |
reg tx_data_ready; | |
reg [7:0] tx_data; | |
uart_tx #( | |
.BAUD_DIVISOR(16000000 / 115200) | |
) uart_tx_inst ( | |
.i_clk(CLK), | |
.o_tx(PIN_24), | |
.o_tx_buf_empty(tx_buf_empty), | |
.i_tx_data_ready(tx_data_ready), | |
.i_tx_data(tx_data) | |
); | |
reg [3:0] ctr = 0; | |
always @(*) begin | |
if (tx_buf_empty) begin | |
if (ctr == 10) begin | |
tx_data <= " "; | |
end else begin | |
tx_data <= "0" + ctr; | |
end | |
tx_data_ready <= 1; | |
end else begin | |
tx_data <= 'h00; | |
tx_data_ready <= 0; | |
end | |
end | |
always @(posedge CLK) begin | |
if (tx_buf_empty) begin | |
if (ctr == 10) begin | |
ctr <= 0; | |
end else begin | |
ctr <= ctr + 1; | |
end | |
end | |
end | |
endmodule |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
`default_nettype none | |
module uart_tx | |
# ( | |
parameter BAUD_DIVISOR = 0, | |
parameter N_START_BITS = 1, | |
parameter N_DATA_BITS = 8, | |
parameter N_STOP_BITS = 1 | |
) ( | |
input i_clk, | |
output o_tx, | |
output o_tx_buf_empty, | |
input i_tx_data_ready, | |
input [N_DATA_BITS-1:0] i_tx_data | |
); | |
localparam SHREG_WIDTH = N_START_BITS + N_DATA_BITS + N_STOP_BITS; | |
localparam START_BITS = {N_START_BITS{1'b0}}; | |
localparam STOP_BITS = {N_STOP_BITS{1'b1}}; | |
localparam STATE_IDLE = 0; | |
localparam STATE_TX = 1; | |
reg state = STATE_IDLE; | |
reg next_state; | |
reg tx; | |
assign o_tx = tx; | |
reg tx_buf_empty = 1; | |
reg [N_DATA_BITS-1:0] tx_buf; | |
assign o_tx_buf_empty = tx_buf_empty; | |
reg [SHREG_WIDTH-1:0] shreg; | |
reg [3:0] num_bits_sent; | |
reg [10:0] ctr; | |
always @(*) begin | |
if (state == STATE_IDLE) begin | |
tx <= 1'b1; | |
if (!tx_buf_empty) begin | |
next_state <= STATE_TX; | |
end else begin | |
next_state <= STATE_IDLE; | |
end | |
end else if (state == STATE_TX) begin | |
tx <= shreg[0]; | |
if ((num_bits_sent == SHREG_WIDTH - 1) & (ctr == BAUD_DIVISOR)) begin | |
next_state <= STATE_IDLE; | |
end else begin | |
next_state <= STATE_TX; | |
end | |
end | |
end | |
always @(posedge i_clk) begin | |
if (i_tx_data_ready & tx_buf_empty) begin | |
tx_buf_empty <= 0; | |
tx_buf <= i_tx_data; | |
end | |
if (state == STATE_IDLE) begin | |
if (!tx_buf_empty) begin | |
tx_buf_empty <= 1; | |
shreg <= {STOP_BITS, tx_buf, START_BITS}; | |
num_bits_sent <= 0; | |
ctr <= 0; | |
end | |
end else if (state == STATE_TX) begin | |
if (ctr == BAUD_DIVISOR) begin | |
shreg <= {1'b0, shreg[SHREG_WIDTH-1:1]}; | |
num_bits_sent <= num_bits_sent + 1; | |
ctr <= 0; | |
end else begin | |
ctr <= ctr + 1; | |
end | |
end | |
state <= next_state; | |
end | |
endmodule |
Thank you so much!!! Really appreciate it and will try and incorporate later :)
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Damn can you really not do inline comments on a gist? I will try to format this in a sensible way. All of these are for
uart_tx.v
Line 14:
input i_tx_data_ready,
*_valid
, signalling to the consumer that the producer has data available*_ready
, signalling to the producer that the consumer will accept data presented on this cycleWith transfer taking place when both are high. So the naming here is just a little unconventional, and could cause confusion.
Line 21-22:
state
a more descriptive nameLine 23:
reg state = STATE_IDLE;
Line 40:
tx <= 1'b1;
always @ (*)
blocks. They are nowhere near as dangerous as blocking assignments in clocked blocks, but can increase simulation time for large designs. Consider using blocking assignments hereLine 49:
if ((num_bits_sent == SHREG_WIDTH - 1) & (ctr == BAUD_DIVISOR)) begin
BAUD_DIVISOR >= 2 ** 11
. Consider sizingctr
with e.g.$clog2(BAUD_DIVISOR + 1)
num_bits_sent
andSHREG_WIDTH
&
and==
(although your code is fine). Consider&&
hereLine 67:
shreg <= {STOP_BITS, tx_buf, START_BITS};
IDLE
state to theTX
stateIDLE
state for one cycle after each byte.IDLE
is strictly necessary, and whether the design could be made cleaner or more orthogonal without itLine 72:
if (ctr == BAUD_DIVISOR) begin
ctr == BAUD_DIVISOR
, one of them in the block wherectr
is updated. It requires a little more context to readctr
are an input to the logic used in these two blocks. You may want to consider generating a single, registeredclk_en
signal from the free-running counter, and using this single bit to enable the downstream logic