forked from tanchou/Verilog
		
	
		
			
	
	
		
			132 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			Coq
		
	
	
	
	
	
		
		
			
		
	
	
			132 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			Coq
		
	
	
	
	
	
|   | 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 |