diff --git a/uart_tx b/uart_tx new file mode 100644 index 0000000..3a441a0 --- /dev/null +++ b/uart_tx @@ -0,0 +1,133 @@ +module uart_tx + #(parameter CLKS_PER_BIT) + ( + input i_Clock, + input i_Tx_DV, + input [7:0] i_Tx_Byte, + output o_Tx_Active, + output reg o_Tx_Serial, + output o_Tx_Done + ); + + parameter s_IDLE = 3'b000; + parameter s_TX_START_BIT = 3'b001; + parameter s_TX_DATA_BITS = 3'b010; + parameter s_TX_STOP_BIT = 3'b011; + parameter s_CLEANUP = 3'b100; + + reg [2:0] r_SM_Main = 0; + reg [7:0] r_Clock_Count = 0; + reg [2:0] r_Bit_Index = 0; + reg [7:0] r_Tx_Data = 0; + reg r_Tx_Done = 0; + reg r_Tx_Active = 0; + + always @(posedge i_Clock) + begin + + case (r_SM_Main) + s_IDLE : + begin + o_Tx_Serial <= 1'b1; // Drive Line High for Idle + r_Tx_Done <= 1'b0; + r_Clock_Count <= 0; + r_Bit_Index <= 0; + + if (i_Tx_DV == 1'b1) + begin + r_Tx_Active <= 1'b1; + r_Tx_Data <= i_Tx_Byte; + r_SM_Main <= s_TX_START_BIT; + end + else + r_SM_Main <= s_IDLE; + end // case: s_IDLE + + + // Send out Start Bit. Start bit = 0 + s_TX_START_BIT : + begin + o_Tx_Serial <= 1'b0; + + // Wait CLKS_PER_BIT-1 clock cycles for start bit to finish + if (r_Clock_Count < CLKS_PER_BIT-1) + begin + r_Clock_Count <= r_Clock_Count + 1; + r_SM_Main <= s_TX_START_BIT; + end + else + begin + r_Clock_Count <= 0; + r_SM_Main <= s_TX_DATA_BITS; + end + end // case: s_TX_START_BIT + + + // Wait CLKS_PER_BIT-1 clock cycles for data bits to finish + s_TX_DATA_BITS : + begin + o_Tx_Serial <= r_Tx_Data[r_Bit_Index]; + + if (r_Clock_Count < CLKS_PER_BIT-1) + begin + r_Clock_Count <= r_Clock_Count + 1; + r_SM_Main <= s_TX_DATA_BITS; + end + else + begin + r_Clock_Count <= 0; + + // Check if we have sent out all bits + if (r_Bit_Index < 7) + begin + r_Bit_Index <= r_Bit_Index + 1; + r_SM_Main <= s_TX_DATA_BITS; + end + else + begin + r_Bit_Index <= 0; + r_SM_Main <= s_TX_STOP_BIT; + end + end + end // case: s_TX_DATA_BITS + + + // Send out Stop bit. Stop bit = 1 + s_TX_STOP_BIT : + begin + o_Tx_Serial <= 1'b1; + + // Wait CLKS_PER_BIT-1 clock cycles for Stop bit to finish + if (r_Clock_Count < CLKS_PER_BIT-1) + begin + r_Clock_Count <= r_Clock_Count + 1; + r_SM_Main <= s_TX_STOP_BIT; + end + else + begin + r_Tx_Done <= 1'b1; + r_Clock_Count <= 0; + r_SM_Main <= s_CLEANUP; + r_Tx_Active <= 1'b0; + end + end // case: s_Tx_STOP_BIT + + + // Stay here 1 clock + s_CLEANUP : + begin + r_Tx_Done <= 1'b1; + r_SM_Main <= s_IDLE; + end + + + default : + r_SM_Main <= s_IDLE; + + endcase + end + + assign o_Tx_Active = r_Tx_Active; + assign o_Tx_Done = r_Tx_Done; + +endmodule