1//-----------------------------------------------------
2// Design Name : uart
3// File Name   : uart.v
4// Function    : Simple UART
5// Coder       : Deepak Kumar Tala
6//-----------------------------------------------------
7module uart (
8reset          ,
9txclk          ,
10ld_tx_data     ,
11tx_data        ,
12tx_enable      ,
13tx_out         ,
14tx_empty       ,
15rxclk          ,
16uld_rx_data    ,
17rx_data        ,
18rx_enable      ,
19rx_in          ,
20rx_empty
21);
22// Port declarations
23input        reset          ;
24input        txclk          ;
25input        ld_tx_data     ;
26input  [7:0] tx_data        ;
27input        tx_enable      ;
28output       tx_out         ;
29output       tx_empty       ;
30input        rxclk          ;
31input        uld_rx_data    ;
32output [7:0] rx_data        ;
33input        rx_enable      ;
34input        rx_in          ;
35output       rx_empty       ;
36
37// Internal Variables
38reg [7:0]    tx_reg         ;
39reg          tx_empty       ;
40reg          tx_over_run    ;
41reg [3:0]    tx_cnt         ;
42reg          tx_out         ;
43reg [7:0]    rx_reg         ;
44reg [7:0]    rx_data        ;
45reg [3:0]    rx_sample_cnt  ;
46reg [3:0]    rx_cnt         ;
47reg          rx_frame_err   ;
48reg          rx_over_run    ;
49reg          rx_empty       ;
50reg          rx_d1          ;
51reg          rx_d2          ;
52reg          rx_busy        ;
53
54// UART RX Logic
55always @ (posedge rxclk or posedge reset)
56if (reset) begin
57  rx_reg        <= 0;
58  rx_data       <= 0;
59  rx_sample_cnt <= 0;
60  rx_cnt        <= 0;
61  rx_frame_err  <= 0;
62  rx_over_run   <= 0;
63  rx_empty      <= 1;
64  rx_d1         <= 1;
65  rx_d2         <= 1;
66  rx_busy       <= 0;
67end else begin
68  // Synchronize the asynch signal
69  rx_d1 <= rx_in;
70  rx_d2 <= rx_d1;
71  // Uload the rx data
72  if (uld_rx_data) begin
73    rx_data  <= rx_reg;
74    rx_empty <= 1;
75  end
76  // Receive data only when rx is enabled
77  if (rx_enable) begin
78    // Check if just received start of frame
79    if (!rx_busy && !rx_d2) begin
80      rx_busy       <= 1;
81      rx_sample_cnt <= 1;
82      rx_cnt        <= 0;
83    end
84    // Start of frame detected, Proceed with rest of data
85    if (rx_busy) begin
86       rx_sample_cnt <= rx_sample_cnt + 1;
87       // Logic to sample at middle of data
88       if (rx_sample_cnt == 7) begin
89          if ((rx_d2 == 1) && (rx_cnt == 0)) begin
90            rx_busy <= 0;
91          end else begin
92            rx_cnt <= rx_cnt + 1;
93            // Start storing the rx data
94            if (rx_cnt > 0 && rx_cnt < 9) begin
95              rx_reg[rx_cnt - 1] <= rx_d2;
96            end
97            if (rx_cnt == 9) begin
98               rx_busy <= 0;
99               // Check if End of frame received correctly
100               if (rx_d2 == 0) begin
101                 rx_frame_err <= 1;
102               end else begin
103                 rx_empty     <= 0;
104                 rx_frame_err <= 0;
105                 // Check if last rx data was not unloaded,
106                 rx_over_run  <= (rx_empty) ? 0 : 1;
107               end
108            end
109          end
110       end
111    end
112  end
113  if (!rx_enable) begin
114    rx_busy <= 0;
115  end
116end
117
118// UART TX Logic
119always @ (posedge txclk or posedge reset)
120if (reset) begin
121  tx_reg        <= 0;
122  tx_empty      <= 1;
123  tx_over_run   <= 0;
124  tx_out        <= 1;
125  tx_cnt        <= 0;
126end else begin
127   if (ld_tx_data) begin
128      if (!tx_empty) begin
129        tx_over_run <= 0;
130      end else begin
131        tx_reg   <= tx_data;
132        tx_empty <= 0;
133      end
134   end
135   if (tx_enable && !tx_empty) begin
136     tx_cnt <= tx_cnt + 1;
137     if (tx_cnt == 0) begin
138       tx_out <= 0;
139     end
140     if (tx_cnt > 0 && tx_cnt < 9) begin
141        tx_out <= tx_reg[tx_cnt -1];
142     end
143     if (tx_cnt == 9) begin
144       tx_out <= 1;
145       tx_cnt <= 0;
146       tx_empty <= 1;
147     end
148   end
149   if (!tx_enable) begin
150     tx_cnt <= 0;
151   end
152end
153
154endmodule
155