module uart_transmitter #( parameter CLOCK_FREQ = 125_000_000, parameter BAUD_RATE = 115_200) ( input clk, input reset, input [7:0] data_in, input data_in_valid, output data_in_ready, output serial_out ); // See diagram in the lab guide localparam SYMBOL_EDGE_TIME = CLOCK_FREQ / BAUD_RATE; localparam CLOCK_COUNTER_WIDTH = $clog2(SYMBOL_EDGE_TIME); wire symbol_edge; wire start; wire tx_running; reg [CLOCK_COUNTER_WIDTH-1:0] clk_counter; reg [9:0] tx_shift; reg [3:0] bit_counter; /* verilator lint_off WIDTH */ assign symbol_edge = (clk_counter == SYMBOL_EDGE_TIME - 1); /* lint_on */ assign tx_running = (bit_counter != 4'd0); assign start = (data_in_valid & !tx_running); assign serial_out = (!tx_running) ? 1'd1 : tx_shift[0]; assign data_in_ready = !tx_running; // Sync transmissions bandwidth always @(posedge clk) begin clk_counter <= (start || reset || symbol_edge) ? 0 : clk_counter + 1; end // Keep track of bits sent always @(posedge clk) begin if (reset) bit_counter <= 0; else if (start) bit_counter <= 10; else if (symbol_edge && tx_running) bit_counter <= bit_counter - 1; end // Send data serially // Send LSB first for receiver to piece together always @(posedge clk) begin if (reset) tx_shift <= 0; else if (start) tx_shift <= {1'd1, data_in, 1'd0}; else if (symbol_edge && tx_running) tx_shift <= {1'd0, tx_shift[9:1]}; end endmodule