forked from tanchou/Verilog
		
	
		
			
				
	
	
		
			132 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			Verilog
		
	
	
	
	
	
			
		
		
	
	
			132 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			Verilog
		
	
	
	
	
	
| 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_enable,
 | |
|     
 | |
|     output reg      tx_ready,
 | |
|     output wire     tx
 | |
| );
 | |
| 
 | |
|     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;
 | |
|     reg [15:0]  cycle_cnt;      //baud counter       
 | |
|     reg         tx_reg;
 | |
|     reg [2:0] bit_cnt; 
 | |
|     reg [7:0] tx_data_latch = 0; 
 | |
| 
 | |
| 
 | |
|     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_enable == 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_ready block
 | |
|         if(rst_p == 1'b1)
 | |
|             tx_ready <= 1'b0;  // Reset
 | |
|         else if(state == IDLE && tx_enable == 1'b1)
 | |
|             tx_ready <= 1'b0;  // Pas prêt tant que les données sont valides
 | |
|         else if(state == IDLE)
 | |
|             tx_ready <= 1'b1;
 | |
|         else if(state == STOP && cycle_cnt == CYCLE - 1)
 | |
|             tx_ready <= 1'b1;  // Prêt une fois le bit STOP envoyé
 | |
|         else
 | |
|             tx_ready <= tx_ready;  // Reste inchangé dans d'autres cas
 | |
|     end
 | |
| 
 | |
| 
 | |
| 
 | |
|     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_enable == 1'b1) begin
 | |
|             tx_data_latch <= data;  // Charger les données de data dans tx_data_latch
 | |
|         end
 | |
|     end
 | |
| 
 | |
| 
 | |
|     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
 |