fpga串口打印计数值作业

fpga串口打印计数值作业

作业4:
在前面第六讲作业3的基础上(带按键消抖的计数器流水灯作业作业3),实现功能:
当按键1操作时,向串口发送按键的编号,以及按键时6位计数器的数值大小。发送的内容为:“NO.按键编号+Times.按键次数”,例如:“NO.1+Times.5”.
当按键2操作时,向串口发送按键的编号,以及按键后6位计数器的数值大小。发送内容同上。

思路:计数值传递,数据+48转为ASC码赋给串口数据存储器。

具体代码如下(复制黏贴都有点累):九个文件
seg_test.v // 顶层文件
uart_test.v
uart_rx.v
uart_tx.v
seg_scan.v
led_test.v
seg_decoder.v
key_debounce.v
count_m10.v

//seg_test.v    

`timescale 1ns / 1ps
//*******************************************************************************/
module seg_test(
                input      clk,
                input      rst_n,
                output[5:0]seg_sel,
                output[7:0]seg_data,
			       input [1:0]      key,
	             output [3:0] led,
              input        uart_rx,
	           output       uart_tx					 
);
					 
reg[31:0] timer_cnt;
reg en_1hz;                          //1 second , 1 counter enable
always@(posedge clk or negedge rst_n)
begin
    if(rst_n == 1'b0)
    begin
        en_1hz <= 1'b0;
        timer_cnt <= 32'd0;
    end
    else if(timer_cnt >= 32'd49_999_999)
    begin
        en_1hz <= 1'b1;
        timer_cnt <= 32'd0;
    end
    else
    begin
        en_1hz <= 1'b0;
        timer_cnt <= timer_cnt + 32'd1; 
    end
end


wire [1:0]button_negedge; //Key falling edge
key_debounce key_debounce_1(
    .clk             (clk),
    .rst             (~rst_n),
    .button_in       (key[0]),
    .button_posedge  (),
    .button_negedge  (button_negedge[0]),
    .button_out      ()
);
key_debounce key_debounce_2(
    .clk             (clk),
    .rst             (~rst_n),
    .button_in       (key[1]),
    .button_posedge  (),
    .button_negedge  (button_negedge[1]),
    .button_out      ()
);
led_test  led_test0
(
	.clk            (clk),           // system clock 50Mhz on board
	.rst_n          (rst_n),         // reset ,low active
	.key_out        (button_negedge),
	.led            (led)            // LED,use for control the LED signal on board
);

uart_test uart_test0
(
	.clk             (clk),           // system clock 50Mhz on board
	.rst_n           (rst_n),         // reset ,low active
   .uart_rx         (uart_rx),
	.uart_tx         (uart_tx),
	.key_out        (button_negedge),
	.count0            (count0),
	.count1            (count1),
	.count2            (count2),
	.count3            (count3),
	.count4            (count4),
	.count5            (count5)
);
wire[3:0] count0;
wire t0;
count_m10 count10_m0(
    .clk    (clk),
    .rst_n  (rst_n),
    .en     (en_1hz),
    .clr    (1'b0),
	 .key      (button_negedge),
    .data   (count0),
    .t      (t0)
 );
wire[3:0] count1;
wire t1;
count_m10 count10_m1(
     .clk    (clk),
     .rst_n  (rst_n),
     .en     (t0),
     .clr    (1'b0),
	 .key      (2'b0),
     .data   (count1),
     .t      (t1)
 );

wire[3:0] count2;
wire t2;
count_m10 count10_m2(
    .clk   (clk),
    .rst_n (rst_n),
    .en    (t1),
    .clr   (1'b0),
	 .key      (2'b0),
    .data  (count2),
    .t     (t2)
);

wire[3:0] count3;
wire t3;
count_m10 count10_m3(
    .clk   (clk),
    .rst_n (rst_n),
    .en    (t2),
    .clr   (1'b0),
	 .key       (2'b0),
    .data  (count3),
    .t     (t3)
);

wire[3:0] count4;
wire t4;
count_m10 count10_m4(
    .clk   (clk),
    .rst_n (rst_n),
    .en    (t3),
    .clr   (1'b0),
	 .key        (2'b0),
    .data  (count4),
    .t     (t4)
);

wire[3:0] count5;
wire t5;
count_m10 count10_m5(
    .clk   (clk),
    .rst_n (rst_n),
    .en    (t4),
    .clr   (1'b0),
	 .key       (2'b0),
    .data  (count5),
    .t     (t5)
);


wire[6:0] seg_data_0;
seg_decoder seg_decoder_m0(
    .bin_data  (count5),
    .seg_data  (seg_data_0)
);
wire[6:0] seg_data_1;
seg_decoder seg_decoder_m1(
    .bin_data  (count4),
    .seg_data  (seg_data_1)
);
wire[6:0] seg_data_2;
seg_decoder seg_decoder_m2(
    .bin_data  (count3),
    .seg_data  (seg_data_2)
);
wire[6:0] seg_data_3;
seg_decoder seg_decoder_m3(
    .bin_data  (count2),
    .seg_data  (seg_data_3)
);
wire[6:0] seg_data_4;
seg_decoder seg_decoder_m4(
    .bin_data  (count1),
    .seg_data  (seg_data_4)
);

wire[6:0] seg_data_5;
seg_decoder seg_decoder_m5(
    .bin_data  (count0),
    .seg_data  (seg_data_5)
);

seg_scan seg_scan_m0(
    .clk        (clk),
    .rst_n      (rst_n),
    .seg_sel    (seg_sel),
    .seg_data   (seg_data),
    .seg_data_0 ({1'b1,seg_data_0}),      //The  decimal point at the highest bit,and low level effecitve
    .seg_data_1 ({1'b1,seg_data_1}), 
    .seg_data_2 ({1'b1,seg_data_2}),
    .seg_data_3 ({1'b1,seg_data_3}),
    .seg_data_4 ({1'b1,seg_data_4}),
    .seg_data_5 ({1'b1,seg_data_5})
);
endmodule 
//seg_scan.v

module seg_scan(
	input           clk,
	input           rst_n,
	output reg[5:0] seg_sel,      //digital led chip select
	output reg[7:0] seg_data,     //eight segment digital tube output,MSB is the decimal point
	input[7:0]      seg_data_0,
	input[7:0]      seg_data_1,
	input[7:0]      seg_data_2,
	input[7:0]      seg_data_3,
	input[7:0]      seg_data_4,
	input[7:0]      seg_data_5
);
parameter SCAN_FREQ = 200;     //scan frequency
parameter CLK_FREQ = 50000000; //clock frequency

parameter SCAN_COUNT = CLK_FREQ /(SCAN_FREQ * 6) - 1;

reg[31:0] scan_timer;  //scan time counter
reg[3:0] scan_sel;     //Scan select counter
always@(posedge clk or negedge rst_n)
begin
	if(rst_n == 1'b0)
	begin
		scan_timer <= 32'd0;
		scan_sel <= 4'd0;
	end
	else if(scan_timer >= SCAN_COUNT)
	begin
		scan_timer <= 32'd0;
		if(scan_sel == 4'd5)
			scan_sel <= 4'd0;
		else
			scan_sel <= scan_sel + 4'd1;
	end
	else
		begin
			scan_timer <= scan_timer + 32'd1;
		end
end
always@(posedge clk or negedge rst_n)
begin
	if(rst_n == 1'b0)
	begin
		seg_sel <= 6'b111111;
		seg_data <= 8'hff;
	end
	else
	begin
		case(scan_sel)
			//first digital led
			4'd0:
			begin
				seg_sel <= 6'b11_1110;
				seg_data <= seg_data_0;
			end
			//second digital led
			4'd1:
			begin
				seg_sel <= 6'b11_1101;
				seg_data <= seg_data_1;
			end
			//...
			4'd2:
			begin
				seg_sel <= 6'b11_1011;
				seg_data <= seg_data_2;
			end
			4'd3:
			begin
				seg_sel <= 6'b11_0111;
				seg_data <= seg_data_3;
			end
			4'd4:
			begin
				seg_sel <= 6'b10_1111;
				seg_data <= seg_data_4;
			end
			4'd5:
			begin
				seg_sel <= 6'b01_1111;
				seg_data <= seg_data_5;
			end
			default:
			begin
				seg_sel <= 6'b11_1111;
				seg_data <= 8'hff;
			end
		endcase
	end
end

endmodule
//seg_decoder.v


//*************************************************************************/
module seg_decoder
(
	input[3:0]      bin_data,     // bin data input
	output reg[6:0] seg_data      // seven segments LED output
);

always@(*)
begin
	case(bin_data)
		4'd0:seg_data <= 7'b100_0000;
		4'd1:seg_data <= 7'b111_1001;
		4'd2:seg_data <= 7'b010_0100;
		4'd3:seg_data <= 7'b011_0000;
		4'd4:seg_data <= 7'b001_1001;
		4'd5:seg_data <= 7'b001_0010;
		4'd6:seg_data <= 7'b000_0010;
		4'd7:seg_data <= 7'b111_1000;
		4'd8:seg_data <= 7'b000_0000;
		4'd9:seg_data <= 7'b001_0000;
		4'ha:seg_data <= 7'b000_1000;
		4'hb:seg_data <= 7'b000_0011;
		4'hc:seg_data <= 7'b100_0110;
		4'hd:seg_data <= 7'b010_0001;
		4'he:seg_data <= 7'b000_0110;
		4'hf:seg_data <= 7'b000_1110;
		default:seg_data <= 7'b111_1111;
	endcase
end
endmodule

//led_test.v
module led_test
(
	input           clk,           // system clock 50Mhz on board
	input           rst_n,         // reset ,low active
	input [1:0]        key_out,
	output reg[3:0] led            // LED,use for control the LED signal on board
);

//define the time counter
reg [31:0]      timer;
reg [3:0]       count;

///按键
reg [0:0]        flag;

always@(posedge clk or negedge rst_n)
begin
	if(!rst_n)
		flag <= 1'd0; 
   else if (key_out==1'd1)   
         flag <= ~flag;	
end
流水灯/	
always@(posedge clk or negedge rst_n)
begin
	if (rst_n == 1'b0)
		timer <= 32'd0;                        
	
	else if(timer == 32'd49_999_999) 
    	   timer <= 32'd0; 
 
	else
       timer <= timer + 32'd1;            
end
	
// LED control
always@(posedge clk or negedge rst_n)
begin
	if (rst_n == 1'b0)
		begin
	   	led <= 4'b0000;
		   count <= 4'd0;
		end   
	else if (flag == 0)   	 		    
	   begin
	    if (timer == 32'd0)        
		  led <= 4'b0001; 
	   else if (timer == 32'd12_499_999)       
		  led <= 4'b0010;
	   else if (timer == 32'd24_999_999)      
		  led <= 4'b0100;
	   else if (timer == 32'd37_499_999)     
		  led <= 4'b1000;	 
	   else if (timer == 32'd49_999_999)      
		  led <= 4'b0000; 	   	
	   end
   else
	   begin  
	       if (timer == 32'd0) 
			 led <= 4'b0000; 
			 else if(timer == 32'd24_999_999) 
			 led <= 4'b1111; 
		end
end
endmodule


//key_debounce.v


`timescale 1 ns / 100 ps
module  key_debounce 
(
    input       clk, 
    input       rst, 
    input       button_in,
    output reg  button_posedge,
    output reg  button_negedge,
    output reg  button_out
);
 ---------------- internal constants --------------
parameter N = 32 ;           // debounce timer bitwidth
parameter FREQ = 50;         //model clock :Mhz
parameter MAX_TIME = 20;     //ms
localparam TIMER_MAX_VAL =   MAX_TIME * 1000 * FREQ;
---------------- internal variables ---------------
reg  [N-1 : 0]  q_reg;      // timing regs
reg  [N-1 : 0]  q_next;
reg DFF1, DFF2;             // input flip-flops
wire q_add;                 // control flags
wire q_reset;
reg button_out_d0;
 ------------------------------------------------------

contenious assignment for counter control
assign q_reset = (DFF1  ^ DFF2);          // xor input flip flops to look for level chage to reset counter
assign q_add = ~(q_reg == TIMER_MAX_VAL); // add to counter when q_reg msb is equal to 0
    
 combo counter to manage q_next 
always @ ( q_reset, q_add, q_reg)
begin
    case( {q_reset , q_add})
        2'b00 :
                q_next <= q_reg;
        2'b01 :
                q_next <= q_reg + 1;
        default :
                q_next <= { N {1'b0} };
    endcase     
end

 Flip flop inputs and q_reg update
always @ ( posedge clk or posedge rst)
begin
    if(rst == 1'b1)
    begin
        DFF1 <= 1'b0;
        DFF2 <= 1'b0;
        q_reg <= { N {1'b0} };
    end
    else
    begin
        DFF1 <= button_in;
        DFF2 <= DFF1;
        q_reg <= q_next;
    end
end

 counter control
always @ ( posedge clk or posedge rst)
begin
	if(rst == 1'b1)
		button_out <= 1'b1;
    else if(q_reg == TIMER_MAX_VAL)
        button_out <= DFF2;
    else
        button_out <= button_out;
end

always @ ( posedge clk or posedge rst)
begin
	if(rst == 1'b1)
	begin
		button_out_d0 <= 1'b1;
		button_posedge <= 1'b0;
		button_negedge <= 1'b0;
	end
	else
	begin
		button_out_d0 <= button_out;
		button_posedge <= ~button_out_d0 & button_out;
		button_negedge <= button_out_d0 & ~button_out;
	end	
end
endmodule


//count_m10.v


module count_m10(
                 input          clk,
                 input          rst_n,
                 input          en,    //Counter enable
                 input          clr,   //Counter synchronous reset 
					
					  input [1:0]        key,
                 output reg[3:0]data,  //counter value
                 output reg     t      // carry enable signal
                );
/				 
按键防抖
reg [0:0]        flag;
reg [0:0]        flag2;



always@(posedge clk or negedge rst_n)
begin
	if(!rst_n)		
		begin flag  <= 1'd0; 
		// flag2 <= 1'd0; 
		 end
   else if (key[0]==1)
	     flag <= ~flag;	  //按键1标志位
  
end					          
///count_10m///
always@(posedge clk or negedge rst_n) 
begin
    if(rst_n==0)
      begin
        data <= 4'd0;
        t <= 1'd0; flag2 <= 1'd0;
       end
    else if(clr)
     begin
        data <= 4'd0;
        t <= 1'd0;      
      end
	 else if(key[1]==1)  
             flag2 <= ~flag2;   //按键2标志位
    else if(en)               //1秒钟使能一次,计数en_1hz满 
     begin
        if(data==4'd9)
          begin
            t<= 1'b1;    //进位使能,data满9,前一位使能可以执行一次操作:data+1
            data <= 4'd0;
          end
		  
********改动部分**********///	  
      
		  else 
		     begin 
			    
			  if ((flag == 0)&&(flag2 == 0))       //按键1和2,有一个按下就停止计数                    
              begin 
					data <= data + 4'd1;
					t <= 1'b0;end
		      else 
			  begin
				    if (flag2 == 1)      //按键2标志位
		           begin  
					  t<= 1'b1; 
					  flag2 <= ~flag2; 
					  end
               else
				     t <= 1'b0; 
			     end  
			  end   
				   
     end
           
	 
	else
        t <= 1'b0;
end

endmodule

//uart_test.v

module uart_test(
	input                        clk,
	input                        rst_n,
	input                        uart_rx,
	output                       uart_tx,
	input    [1:0]               key_out,
	input      [3:0]                  count0,
	input      [3:0]                  count1,
	input      [3:0]                  count2,
	input      [3:0]                  count3,
	input      [3:0]                  count4,
	input      [3:0]                  count5
);

parameter                        CLK_FRE = 50;//Mhz
localparam                       IDLE =  0;
localparam                       SEND =  1;   //send HELLO ALINX\r\n
localparam                       WAIT =  2;   //wait 1 second and send uart received data 
reg[7:0]                         tx_data;
reg[7:0]                         tx_str;
reg                              tx_data_valid;
wire                             tx_data_ready;
reg[7:0]                         tx_cnt;
wire[7:0]                        rx_data;
wire                             rx_data_valid;
wire                             rx_data_ready;
reg[31:0]                        wait_cnt;
reg[3:0]                         state;

assign rx_data_ready = 1'b1;//always can receive data,
							//if HELLO ALINX\r\n is being sent, the received data is discarded


always@(posedge clk or negedge rst_n)
begin
	if(rst_n == 1'b0)
	begin
		wait_cnt <= 32'd0;
		tx_data <= 8'd0;
		state <= IDLE;
		tx_cnt <= 8'd0;
		tx_data_valid <= 1'b0;
	end
	
	else 
	begin
	case(state)
		IDLE:if(flag1 || flag2)
			  state <= SEND;
		SEND:
		begin
			wait_cnt <= 32'd0;
			tx_data <= tx_str;

			if(tx_data_valid == 1'b1 && tx_data_ready == 1'b1 && tx_cnt < 8'd15)//Send x bytes data
			begin
				tx_cnt <= tx_cnt + 8'd1; //Send data counter
			end
			else if(tx_data_valid && tx_data_ready)//last byte sent is complete
			begin
				tx_cnt <= 8'd0;
				tx_data_valid <= 1'b0;
				state <= IDLE;///
			end
			else if(~tx_data_valid)
			begin
				tx_data_valid <= 1'b1;
			end
		end
		WAIT:
		begin
			wait_cnt <= wait_cnt + 32'd1;

			if(rx_data_valid == 1'b1)
			begin
				tx_data_valid <= 1'b1;
				tx_data <= rx_data;   // send uart received data
			end
			else if(tx_data_valid && tx_data_ready)
			begin
				tx_data_valid <= 1'b0;
			end
			else if(wait_cnt >= CLK_FRE * 1000000) // wait for 1 second
				state <= IDLE;
		end
		default:
			state <= IDLE;
	endcase
	end
		 
end
reg [0:0]        flag1;
reg [0:0]        flag2;
reg[7:0]          time1;
reg[7:0]          time2;
reg[7:0]          time1_1;
reg[7:0]          time2_1;
always@(posedge clk or negedge rst_n)
begin 
if(rst_n == 1'b0)
	begin
	flag1<= 1'd0; flag2<= 1'd0;
	time1<= 8'd0; time2<= 8'd0;
	time1_1<= 8'd0; time2_1<= 8'd0;
	end
else if (key_out[0]==1'd1)   
  begin
     if (time1 == 8'd9)
       begin 
	    time1_1<= time1_1 +8'd1; time1<= 8'd0;flag1 <= 1'd1;
	    end  
	  else  
	    begin flag1 <= 1'd1; time1 <= time1 +8'd1;end
  end  
else if (key_out[1]==1'd1)  
   begin 
	  if (time2 == 8'd9)
       begin 
		 time2_1<= time2_1 +8'd1; time2<= 8'd0;flag2 <= 1'd1;
		 end 
	  else
		 begin flag2 <= 1'd1; time2 <= time2 +8'd1;end
	end 
else if (tx_cnt == 8'd15)
   begin 
     flag1<= 1'd0; 
     flag2<= 1'd0;
    end
 
 
end
//combinational logic
//Send "HELLO ALINX\r\n"    一个字符占一个字节
always@(*)
begin
 if(flag1||flag2)
  begin
	case(tx_cnt)
		8'd0 :  tx_str <= "N";
		8'd1 :  tx_str <= "O";
		8'd2 :  tx_str <= ".";
		8'd3 :  if(flag1) tx_str <= "1";else tx_str <= "2";
		8'd4 :  tx_str <= "+";
		8'd5 :  tx_str <= count5+ 8'd48;
		8'd6 :  tx_str <= count4+ 8'd48;        
		8'd7 :  tx_str <= count3+ 8'd48;
		8'd8 :  tx_str <= count2+ 8'd48;
		8'd9 :  tx_str <= count1+ 8'd48;
		8'd10:  tx_str <= count0+ 8'd48;
		8'd11:  tx_str <= ".";
		8'd12:  if(flag1) tx_str <= time1_1+ 8'd48;else tx_str <=time2_1+ 8'd48;
		8'd13:  if(flag1) tx_str <= time1+ 8'd48;else tx_str <=time2+ 8'd48;
		8'd14:  tx_str <= "\r";
		8'd15:  tx_str <= "\n";
		default:tx_str <= tx_str;
	endcase
	end

end

uart_rx#
(
	.CLK_FRE(CLK_FRE),
	.BAUD_RATE(115200)
) uart_rx_inst
(
	.clk                        (clk                      ),
	.rst_n                      (rst_n                    ),
	.rx_data                    (rx_data                  ),
	.rx_data_valid              (rx_data_valid            ),
	.rx_data_ready              (rx_data_ready            ),
	.rx_pin                     (uart_rx                  )
);

uart_tx#
(
	.CLK_FRE(CLK_FRE),
	.BAUD_RATE(115200)
) uart_tx_inst
(
	.clk                        (clk                      ),
	.rst_n                      (rst_n                    ),
	.tx_data                    (tx_data                  ),
	.tx_data_valid              (tx_data_valid            ),
	.tx_data_ready              (tx_data_ready            ),
	.tx_pin                     (uart_tx                  )
);
endmodule

//uart_rx.v

module uart_rx
#(
	parameter CLK_FRE = 50,      //clock frequency(Mhz)
	parameter BAUD_RATE = 115200 //serial baud rate
)
(
	input                        clk,              //clock input
	input                        rst_n,            //asynchronous reset input, low active 
	output reg[7:0]              rx_data,          //received serial data
	output reg                   rx_data_valid,    //received serial data is valid
	input                        rx_data_ready,    //data receiver module ready
	input                        rx_pin            //serial data input
);
//calculates the clock cycle for baud rate 
localparam                       CYCLE = CLK_FRE * 1000000 / BAUD_RATE;
//state machine code
localparam                       S_IDLE      = 1;
localparam                       S_START     = 2; //start bit
localparam                       S_REC_BYTE  = 3; //data bits
localparam                       S_STOP      = 4; //stop bit
localparam                       S_DATA      = 5;

reg[2:0]                         state;
reg[2:0]                         next_state;
reg                              rx_d0;            //delay 1 clock for rx_pin
reg                              rx_d1;            //delay 1 clock for rx_d0
wire                             rx_negedge;       //negedge of rx_pin
reg[7:0]                         rx_bits;          //temporary storage of received data
reg[15:0]                        cycle_cnt;        //baud counter
reg[2:0]                         bit_cnt;          //bit counter

assign rx_negedge = rx_d1 && ~rx_d0;

always@(posedge clk or negedge rst_n)
begin
	if(rst_n == 1'b0)
	begin
		rx_d0 <= 1'b0;
		rx_d1 <= 1'b0;	
	end
	else
	begin
		rx_d0 <= rx_pin;
		rx_d1 <= rx_d0;
	end
end


always@(posedge clk or negedge rst_n)
begin
	if(rst_n == 1'b0)
		state <= S_IDLE;
	else
		state <= next_state;
end

always@(*)
begin
	case(state)
		S_IDLE:
			if(rx_negedge)
				next_state <= S_START;
			else
				next_state <= S_IDLE;
		S_START:
			if(cycle_cnt == CYCLE - 1)//one data cycle 
				next_state <= S_REC_BYTE;
			else
				next_state <= S_START;
		S_REC_BYTE:
			if(cycle_cnt == CYCLE - 1  && bit_cnt == 3'd7)  //receive 8bit data
				next_state <= S_STOP;
			else
				next_state <= S_REC_BYTE;
		S_STOP:
			if(cycle_cnt == CYCLE/2 - 1)//half bit cycle,to avoid missing the next byte receiver
				next_state <= S_DATA;
			else
				next_state <= S_STOP;
		S_DATA:
			if(rx_data_ready)    //data receive complete
				next_state <= S_IDLE;
			else
				next_state <= S_DATA;
		default:
			next_state <= S_IDLE;
	endcase
end

always@(posedge clk or negedge rst_n)
begin
	if(rst_n == 1'b0)
		rx_data_valid <= 1'b0;
	else if(state == S_STOP && next_state != state)
		rx_data_valid <= 1'b1;
	else if(state == S_DATA && rx_data_ready)
		rx_data_valid <= 1'b0;
end

always@(posedge clk or negedge rst_n)
begin
	if(rst_n == 1'b0)
		rx_data <= 8'd0;
	else if(state == S_STOP && next_state != state)
		rx_data <= rx_bits;//latch received data
end

always@(posedge clk or negedge rst_n)
begin
	if(rst_n == 1'b0)
		begin
			bit_cnt <= 3'd0;
		end
	else if(state == S_REC_BYTE)
		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 negedge rst_n)
begin
	if(rst_n == 1'b0)
		cycle_cnt <= 16'd0;
	else if((state == S_REC_BYTE && cycle_cnt == CYCLE - 1) || next_state != state)
		cycle_cnt <= 16'd0;
	else
		cycle_cnt <= cycle_cnt + 16'd1;	
end
//receive serial data bit data
always@(posedge clk or negedge rst_n)
begin
	if(rst_n == 1'b0)
		rx_bits <= 8'd0;
	else if(state == S_REC_BYTE && cycle_cnt == CYCLE/2 - 1)
		rx_bits[bit_cnt] <= rx_pin;
	else
		rx_bits <= rx_bits; 
end
endmodule 
//uart_tx.v
//*******************************************************************************/
module uart_tx
#(
	parameter CLK_FRE = 50,      //clock frequency(Mhz)
	parameter BAUD_RATE = 115200 //serial baud rate
)
(
	input                        clk,              //clock input
	input                        rst_n,            //asynchronous reset input, low active 
	input[7:0]                   tx_data,          //data to send
	input                        tx_data_valid,    //data to be sent is valid
	output reg                   tx_data_ready,    //send ready
	output                       tx_pin            //serial data output
);
//calculates the clock cycle for baud rate 
localparam                       CYCLE = CLK_FRE * 1000000 / BAUD_RATE;
//state machine code
localparam                       S_IDLE       = 1;
localparam                       S_START      = 2;//start bit
localparam                       S_SEND_BYTE  = 3;//data bits
localparam                       S_STOP       = 4;//stop bit
reg[2:0]                         state;
reg[2:0]                         next_state;
reg[15:0]                        cycle_cnt; //baud counter
reg[2:0]                         bit_cnt;//bit counter
reg[7:0]                         tx_data_latch; //latch data to send
reg                              tx_reg; //serial data output
assign tx_pin = tx_reg;
always@(posedge clk or negedge rst_n)
begin
	if(rst_n == 1'b0)
		state <= S_IDLE;
	else
		state <= next_state;
end

always@(*)
begin
	case(state)
		S_IDLE:
			if(tx_data_valid == 1'b1)
				next_state <= S_START;
			else
				next_state <= S_IDLE;
		S_START:
			if(cycle_cnt == CYCLE - 1)
				next_state <= S_SEND_BYTE;
			else
				next_state <= S_START;
		S_SEND_BYTE:
			if(cycle_cnt == CYCLE - 1  && bit_cnt == 3'd7)
				next_state <= S_STOP;
			else
				next_state <= S_SEND_BYTE;
		S_STOP:
			if(cycle_cnt == CYCLE - 1)
				next_state <= S_IDLE;
			else
				next_state <= S_STOP;
		default:
			next_state <= S_IDLE;
	endcase
end
always@(posedge clk or negedge rst_n)
begin
	if(rst_n == 1'b0)
		begin
			tx_data_ready <= 1'b0;
		end
	else if(state == S_IDLE)
		if(tx_data_valid == 1'b1)
			tx_data_ready <= 1'b0;
		else
			tx_data_ready <= 1'b1;
	else if(state == S_STOP && cycle_cnt == CYCLE - 1)
			tx_data_ready <= 1'b1;
end


always@(posedge clk or negedge rst_n)
begin
	if(rst_n == 1'b0)
		begin
			tx_data_latch <= 8'd0;
		end
	else if(state == S_IDLE && tx_data_valid == 1'b1)
			tx_data_latch <= tx_data;
		
end

always@(posedge clk or negedge rst_n)
begin
	if(rst_n == 1'b0)
		begin
			bit_cnt <= 3'd0;
		end
	else if(state == S_SEND_BYTE)
		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 negedge rst_n)
begin
	if(rst_n == 1'b0)
		cycle_cnt <= 16'd0;
	else if((state == S_SEND_BYTE && cycle_cnt == CYCLE - 1) || next_state != state)
		cycle_cnt <= 16'd0;
	else
		cycle_cnt <= cycle_cnt + 16'd1;	
end

always@(posedge clk or negedge rst_n)
begin
	if(rst_n == 1'b0)
		tx_reg <= 1'b1;
	else
		case(state)
			S_IDLE,S_STOP:
				tx_reg <= 1'b1; 
			S_START:
				tx_reg <= 1'b0; 
			S_SEND_BYTE:
				tx_reg <= tx_data_latch[bit_cnt];
			default:
				tx_reg <= 1'b1; 
		endcase
end

endmodule 
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
FPGA串口通信是指使用FPGA芯片进行串口数据传输的通信方式。在FPGA串口通信中,常用的通信协议是RS485。RS485是一种常见的串口通信标准,它可以实现长距离的数据传输,传输速率可以根据需求进行调整。 在FPGA串口通信中,数据的传输是通过串口回环的方式实现的。数据从发送端经过串行信号传输到FPGA芯片,然后通过并行处理提取出有效的数据位,最后将数据发送给接收端。接收端也通过串行信号接收数据,并将数据解析出来,进行后续处理。 在进行数据采样时,最好选择稳定的信号进行采样。为了提取有效的数据位,需要加入data_in信号。通过对data_in信号进行处理,可以提取出有效的数据位,以便进行后续的数据处理。 在接收端设计文件中,输入的串行数据rxd包含了停止位和起始位,但只有数据位这8位是需要的有效数据。因此,在接收端设计文件中,需要对输入的串行数据进行解析,提取出有效的数据位,并进行后续的处理。 综上所述,FPGA串口通信是通过FPGA芯片进行串口数据传输的一种通信方式,可以使用RS485协议实现长距离的数据传输。在进行数据采样时,需要选择稳定的信号,并通过对数据进行处理提取出有效的数据位。在接收端设计文件中,需要对输入的串行数据进行解析,提取出有效的数据位,并进行后续的处理。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值