| 
									
										
										
										
											2025-04-28 17:13:39 +02:00
										 |  |  | module uart_tx #( | 
					
						
							|  |  |  | 	parameter       CLK_FREQ = 27_000_000, | 
					
						
							|  |  |  | 	parameter       BAUD_RATE = 115200 | 
					
						
							|  |  |  | )( | 
					
						
							|  |  |  |     input wire      clk, | 
					
						
							|  |  |  |     input wire      rst_p, | 
					
						
							|  |  |  |     input wire[7:0] data, | 
					
						
							|  |  |  |     input wire      tx_data_valid, | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     output wire     tx, | 
					
						
							|  |  |  |     output reg      tx_data_ready | 
					
						
							|  |  |  | ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     localparam CYCLE = CLK_FREQ / BAUD_RATE;  | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     localparam IDLE  = 2'd0; | 
					
						
							|  |  |  |     localparam START = 2'd1; | 
					
						
							|  |  |  |     localparam DATA  = 2'd2; | 
					
						
							|  |  |  |     localparam STOP  = 2'd3; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     reg [1:0]   state = IDLE; | 
					
						
							|  |  |  |     reg [1:0]   next_state; | 
					
						
							| 
									
										
										
										
											2025-05-02 11:03:14 +02:00
										 |  |  |     reg [15:0]  cycle_cnt;      //baud counter        | 
					
						
							| 
									
										
										
										
											2025-04-28 17:13:39 +02:00
										 |  |  |     reg         tx_reg; | 
					
						
							| 
									
										
										
										
											2025-05-02 11:03:14 +02:00
										 |  |  |     reg [2:0] bit_cnt;  | 
					
						
							|  |  |  |     reg [7:0] tx_data_latch = 0;  | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-04-28 17:13:39 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     assign tx = tx_reg; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     always@(posedge clk or posedge rst_p)begin // Avance d'etat  | 
					
						
							|  |  |  |         if(rst_p == 1'b1) | 
					
						
							|  |  |  |             state <= IDLE; | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |             state <= next_state; | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     always@(*) begin
 | 
					
						
							|  |  |  |         case(state) | 
					
						
							|  |  |  |             IDLE: | 
					
						
							|  |  |  |                 if(tx_data_valid == 1'b1) | 
					
						
							|  |  |  |                     next_state = START; | 
					
						
							|  |  |  |                 else | 
					
						
							|  |  |  |                     next_state = IDLE; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             START: | 
					
						
							|  |  |  |                 if(cycle_cnt == CYCLE - 1) | 
					
						
							|  |  |  |                     next_state = DATA; | 
					
						
							|  |  |  |                 else | 
					
						
							|  |  |  |                     next_state = START; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             DATA: | 
					
						
							|  |  |  |                 if(cycle_cnt == CYCLE - 1  && bit_cnt == 3'd7) | 
					
						
							|  |  |  |                     next_state = STOP; | 
					
						
							|  |  |  |                 else | 
					
						
							|  |  |  |                     next_state = DATA; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             STOP: | 
					
						
							|  |  |  |                 if(cycle_cnt == CYCLE - 1) | 
					
						
							|  |  |  |                     next_state = IDLE; | 
					
						
							|  |  |  |                 else | 
					
						
							|  |  |  |                     next_state = STOP; | 
					
						
							|  |  |  |             default: | 
					
						
							|  |  |  |                 next_state = IDLE; | 
					
						
							|  |  |  |         endcase | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     always@(posedge clk or posedge rst_p)begin  // tx_data_ready block | 
					
						
							|  |  |  |         if(rst_p == 1'b1) | 
					
						
							| 
									
										
										
										
											2025-05-02 11:03:14 +02:00
										 |  |  |             tx_data_ready <= 1'b0;  // Reset | 
					
						
							|  |  |  |         else if(state == IDLE && tx_data_valid == 1'b1) | 
					
						
							|  |  |  |             tx_data_ready <= 1'b0;  // Pas prêt tant que les données sont valides | 
					
						
							| 
									
										
										
										
											2025-04-28 17:13:39 +02:00
										 |  |  |         else if(state == IDLE) | 
					
						
							| 
									
										
										
										
											2025-05-02 11:03:14 +02:00
										 |  |  |             tx_data_ready <= 1'b1; | 
					
						
							| 
									
										
										
										
											2025-04-28 17:13:39 +02:00
										 |  |  |         else if(state == STOP && cycle_cnt == CYCLE - 1) | 
					
						
							| 
									
										
										
										
											2025-05-02 11:03:14 +02:00
										 |  |  |             tx_data_ready <= 1'b1;  // Prêt une fois le bit STOP envoyé | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |             tx_data_ready <= tx_data_ready;  // Reste inchangé dans d'autres cas | 
					
						
							| 
									
										
										
										
											2025-04-28 17:13:39 +02:00
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-05-02 11:03:14 +02:00
										 |  |  |     always@(posedge clk or posedge rst_p) begin // tx_data_latch block | 
					
						
							|  |  |  |         if(rst_p == 1'b1) begin | 
					
						
							|  |  |  |             tx_data_latch <= 8'd0; | 
					
						
							|  |  |  |         end else if(state == IDLE && tx_data_valid == 1'b1) begin | 
					
						
							|  |  |  |             tx_data_latch <= data;  // Charger les données de `data` dans `tx_data_latch` | 
					
						
							|  |  |  |         end | 
					
						
							| 
									
										
										
										
											2025-04-28 17:13:39 +02:00
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-05-02 11:03:14 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-04-28 17:13:39 +02:00
										 |  |  |     always@(posedge clk or posedge rst_p)begin  // DATA bit_cnt block | 
					
						
							|  |  |  |         if(rst_p == 1'b1)begin | 
					
						
							|  |  |  |                 bit_cnt <= 3'd0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         end else if(state == DATA) | 
					
						
							|  |  |  |             if(cycle_cnt == CYCLE - 1) | 
					
						
							|  |  |  |                 bit_cnt <= bit_cnt + 3'd1; | 
					
						
							|  |  |  |             else | 
					
						
							|  |  |  |                 bit_cnt <= bit_cnt; | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |             bit_cnt <= 3'd0; | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     always@(posedge clk or posedge rst_p)begin  // Cycle counter | 
					
						
							|  |  |  |         if(rst_p == 1'b1) | 
					
						
							|  |  |  |             cycle_cnt <= 16'd0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         else if((state == DATA && cycle_cnt == CYCLE - 1) || next_state != state) | 
					
						
							|  |  |  |             cycle_cnt <= 16'd0; | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |             cycle_cnt <= cycle_cnt + 16'd1;	 | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     always@(posedge clk or posedge rst_p)begin  // tx state managment | 
					
						
							|  |  |  |         if(rst_p == 1'b1) | 
					
						
							|  |  |  |             tx_reg <= 1'b1; | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |             case(state) | 
					
						
							|  |  |  |                 IDLE,STOP: | 
					
						
							|  |  |  |                     tx_reg <= 1'b1;  | 
					
						
							|  |  |  |                 START: | 
					
						
							|  |  |  |                     tx_reg <= 1'b0;  | 
					
						
							|  |  |  |                 DATA: | 
					
						
							|  |  |  |                     tx_reg <= tx_data_latch[bit_cnt]; // SENDING BYTE HERE | 
					
						
							|  |  |  |                 default: | 
					
						
							|  |  |  |                     tx_reg <= 1'b1;  | 
					
						
							|  |  |  |             endcase | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | endmodule |