Пример реализации UART

//-----------------------------------------------------
// Имя модуля : uart
// Имя файла : uart.v
// Функц. назначение : Простой UART
// Программист : www.portal-ed.ru/
//-----------------------------------------------------
module uart (
reset ,
txclk ,
ld_tx_data ,
tx_data ,
tx_enable ,
tx_out ,
tx_empty ,
rxclk ,
uld_rx_data ,
rx_data ,
rx_enable ,
rx_in ,
rx_empty
);
// Объявление портов
input reset ;
input txclk ;
input ld_tx_data ;
input [7:0] tx_data ;
input tx_enable ;
output tx_out ;
output tx_empty ;
input rxclk ;
input uld_rx_data ;
output [7:0] rx_data ;
input rx_enable ;
input rx_in ;
output rx_empty ;
// Внутренние переменные
reg [7:0] tx_reg ;
reg tx_empty ;
reg tx_over_run ;
reg [3:0] tx_cnt ;
reg tx_out ;
reg [7:0] rx_reg ;
reg [7:0] rx_data ;
reg [3:0] rx_sample_cnt ;
reg [3:0] rx_cnt ;
reg rx_frame_err ;
reg rx_over_run ;
reg rx_empty ;
reg rx_d1 ;
reg rx_d2 ;
reg rx_busy ;
// Логика UART приема
always @ (posedge rxclk or posedge reset)
if (reset) begin
rx_reg <= 0;
rx_data <= 0;
rx_sample_cnt <= 0;
rx_cnt <= 0;
rx_frame_err <= 0;
rx_over_run <= 0;
rx_empty <= 1;
rx_d1 <= 1;
rx_d2 <= 1;
rx_busy <= 0;
end else begin
// Синхронный и асинхронный сигнал
rx_d1 <= rx_in;
rx_d2 <= rx_d1;
// Загрузка принятых данных
if (uld_rx_data) begin
rx_data <= rx_reg;
rx_empty <= 1;
end
// Приём данных только тогда, когда разрешен приём
if (rx_enable) begin
// Проверка того, что получено начало кадра
if (!rx_busy && !rx_d2) begin
                                 rx_busy <= 1;
                                 rx_sample_cnt <= 1;
                                 rx_cnt <= 0;
                                 end
// Начало кадра обнаружено, переходим к остальным данным
if (rx_busy) begin
                rx_sample_cnt <= rx_sample_cnt + 1;
                if (rx_sample_cnt == 7) begin
                                                   if ((rx_d2 == 1) && (rx_cnt == 0)) begin
                                                                                                      rx_busy <= 0;
                                                                                                      end else begin
                                                                                                                     rx_cnt <= rx_cnt + 1;
// Начало сохранения данных приёма
if (rx_cnt > 0 && rx_cnt < 9) begin
                                          rx_reg[rx_cnt - 1] <= rx_d2;
                                          end
if (rx_cnt == 9) begin
                       rx_busy <= 0;
// Проверка конца кадра, т.е. кадр принят корректно
if (rx_d2 == 0) begin
                       rx_frame_err <= 1;
                      end else begin
                                    rx_empty <= 0;
                                    rx_frame_err <= 0;
                                    rx_over_run <= (rx_empty) ? 0 : 1;
                                    end
end
end
end
end
end
if (!rx_enable) begin
                     rx_busy <= 0;
                     end
end
// UART передатчик
always @ (posedge txclk or posedge reset)
if (reset) begin
              tx_reg <= 0;
             tx_empty <= 1;
             tx_over_run <= 0;
             tx_out <= 1;
             tx_cnt <= 0;
             end else begin
                           if (ld_tx_data) begin
                                                if (!tx_empty) begin
                                                                     tx_over_run <= 0;
                                                                     end else begin
                                                                                   tx_reg <= tx_data;
                                                                                   tx_empty <= 0;
                                                                                   end
end
if (tx_enable && !tx_empty) begin
                                        tx_cnt <= tx_cnt + 1;
                                        if (tx_cnt == 0) begin
                                                                tx_out <= 0;
end
if (tx_cnt > 0 && tx_cnt < 9) begin
                                           tx_out <= tx_reg[tx_cnt -1];
                                           end
if (tx_cnt == 9) begin
                        tx_out <= 1;
                        tx_cnt <= 0;
                        tx_empty <= 1;
                        end
end
if (!tx_enable) begin
                     tx_cnt <= 0;
                     end
end
endmodule