added missing rtl
diff --git a/verilog/rtl/uart_rx_prog.v b/verilog/rtl/uart_rx_prog.v new file mode 100644 index 0000000..23016da --- /dev/null +++ b/verilog/rtl/uart_rx_prog.v
@@ -0,0 +1,157 @@ +`timescale 1ns / 1ps +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +// Set Parameter CLKS_PER_BIT as follows: +// CLKS_PER_BIT = (Frequency of i_Clock)/(Frequency of UART) +// Example: 10 MHz Clock, 115200 baud UART +// (10000000)/(115200) = 87 + +module uart_rx_prog ( + input wire clk_i, + input wire rst_ni, + input wire i_Rx_Serial, + input wire [15:0] CLKS_PER_BIT, + output wire o_Rx_DV, + output wire [7:0] o_Rx_Byte + ); + + parameter s_IDLE = 3'b000; + parameter s_RX_START_BIT = 3'b001; + parameter s_RX_DATA_BITS = 3'b010; + parameter s_RX_STOP_BIT = 3'b011; + parameter s_CLEANUP = 3'b100; + + reg r_Rx_Data_R ; + reg r_Rx_Data ; + + reg [15:0] r_Clock_Count ; + reg [2:0] r_Bit_Index ; //8 bits total + reg [7:0] r_Rx_Byte ; + reg r_Rx_DV ; + reg [2:0] r_SM_Main ; + + // Purpose: Double-register the incoming data. + // This allows it to be used in the UART RX Clock Domain. + // (It removes problems caused by metastability) + always @(posedge clk_i) + begin + if (~rst_ni) begin + r_Rx_Data_R <= 1'b1; + r_Rx_Data <= 1'b1; + end else begin + r_Rx_Data_R <= i_Rx_Serial; + r_Rx_Data <= r_Rx_Data_R; + end + end + + + // Purpose: Control RX state machine + always @(posedge clk_i or negedge rst_ni) + begin + if (~rst_ni) begin + r_SM_Main <= s_IDLE; + r_Rx_DV <= 1'b0; + r_Clock_Count <= 16'b0; + r_Bit_Index <= 3'b0; + r_Rx_Byte <= 8'b0; + end else begin + case (r_SM_Main) + s_IDLE : + begin + r_Rx_DV <= 1'b0; + r_Clock_Count <= 16'b0; + r_Bit_Index <= 3'b0; + r_Rx_Byte <= 8'b0; + if (r_Rx_Data == 1'b0) // Start bit detected + r_SM_Main <= s_RX_START_BIT; + else + r_SM_Main <= s_IDLE; + end + + // Check middle of start bit to make sure it's still low + s_RX_START_BIT : + begin + if (r_Clock_Count == ((CLKS_PER_BIT-1)>>1)) + begin + if (r_Rx_Data == 1'b0) + begin + r_Clock_Count <= 16'b0; // reset counter, found the middle + r_SM_Main <= s_RX_DATA_BITS; + end + else + r_SM_Main <= s_IDLE; + end + else + begin + r_Clock_Count <= r_Clock_Count + 16'b1; + r_SM_Main <= s_RX_START_BIT; + end + end // case: s_RX_START_BIT + + + // Wait CLKS_PER_BIT-1 clock cycles to sample serial data + s_RX_DATA_BITS : + begin + if (r_Clock_Count < CLKS_PER_BIT-1) + begin + r_Clock_Count <= r_Clock_Count + 16'b1; + r_SM_Main <= s_RX_DATA_BITS; + end + else + begin + r_Clock_Count <= 16'b0; + r_Rx_Byte[r_Bit_Index] <= r_Rx_Data; + + // Check if we have received all bits + if (r_Bit_Index < 7) + begin + r_Bit_Index <= r_Bit_Index + 3'b1; + r_SM_Main <= s_RX_DATA_BITS; + end + else + begin + r_Bit_Index <= 3'b0; + r_SM_Main <= s_RX_STOP_BIT; + end + end + end // case: s_RX_DATA_BITS + + + // Receive Stop bit. Stop bit = 1 + s_RX_STOP_BIT : + begin + // 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 + 16'b1; + r_SM_Main <= s_RX_STOP_BIT; + end + else + begin + r_Rx_DV <= 1'b1; + r_Clock_Count <= 16'b0; + r_SM_Main <= s_CLEANUP; + end + end // case: s_RX_STOP_BIT + + + // Stay here 1 clock + s_CLEANUP : + begin + r_SM_Main <= s_IDLE; + r_Rx_DV <= 1'b0; + end + + + default : + r_SM_Main <= s_IDLE; + + endcase + end + end + + assign o_Rx_DV = r_Rx_DV; + assign o_Rx_Byte = r_Rx_Byte; + +endmodule // uart_rx