4、vivado之uart串口数据发送与接收

编程入门 行业动态 更新时间:2024-10-18 11:25:04

4、vivado之uart<a href=https://www.elefans.com/category/jswz/34/1769224.html style=串口数据发送与接收"/>

4、vivado之uart串口数据发送与接收

文章目录

  • 实验目标
  • 实验原理
    • 串口协议
    • 状态机设定
    • 关于波特率,采用115200的波特率设计
  • 实验代码
    • rx_uart
    • uart_tx
    • uart_top
  • 实验结果
    • 仿真结果
    • 仿真代码
    • 上电测试
  • 总结

实验目标

常态下,fpga 侧实现1s一次的的数据发送。在空闲的时候, fpga侧实现串口的数据的接收,然后再通过串口将数据返回给上位机

实验原理

串口协议

状态机设定

关于波特率,采用115200的波特率设计

实验代码

说明:以下的代码是我照着黑金的修改后,形成的自己的代码,要看原来的代码可以参考黑金的资料。

rx_uart

`timescale 1ns / 1ps
/*
模块功能简介
接收来自rx_pin 的 uart 数据v
将接收到的数据完成后,将我们的数据的rx_data_valid 置位有效# 然后将收到的数据 通过rx_data 发送出去*/module uart_rx#( parameter clk_fre = 50,parameter baud_rate = 115200
)
(input clk,input rst_n,input rx_pin,input rx_data_ready,output reg rx_data_valid,output reg [7:0] rx_data
);
//calculates the clock cycle for baud rate 
localparam cycle = clk_fre * 1000000/baud_rate;
parameter rx_idle=3'b000;
parameter rx_start=3'b001;
parameter rx_rcv_byte=3'b010;
parameter rx_stop=3'b011;
parameter rx_data_state =3'b100;reg [2:0]rx_state=0;
reg [2:0]next_stae;
reg rx_d0;
reg rx_d1;wire rx_negedge;
reg [7:0] rx_bits=0;
reg [15:0] cycle_cnt=0;
reg [2:0] bit_cnt=0;assign rx_negedge = rx_d1 && ~rx_d0;// This part is for detecting the start of the translation f
always @(posedge clk or negedge rst_n)
beginif (rst_n ==1'b0)beginrx_d0 <=0;rx_d1 <=0;endelse beginrx_d0 <= rx_pin;rx_d1 <= rx_d0; end
endalways@(posedge clk or negedge rst_n)
beginif (rst_n == 1'b0)beginrx_state <= rx_idle;rx_data_valid <= 1'b0;endelse begincase(rx_state)rx_idle:beginif(rx_negedge == 1'b1)rx_state <= rx_start;elserx_state <= rx_idle;endrx_start:beginif(cycle_cnt == cycle -1)beginrx_state <= rx_rcv_byte;cycle_cnt <= 16'd0;endelsebeginrx_state <= rx_start;cycle_cnt <= cycle_cnt + 16'd1;endendrx_rcv_byte:beginif(cycle_cnt == cycle - 1)//分成两种情况,达到8个bit/没到8个字节beginif(bit_cnt == 3'd7)beginrx_state <= rx_stop;bit_cnt <= 3'd0;cycle_cnt <= 16'd0;endelsebeginbit_cnt <= bit_cnt + 3'd1;cycle_cnt <= 16'd0;endendelse if (cycle_cnt == cycle/2 -1)beginrx_bits[bit_cnt] <= rx_pin;cycle_cnt <= cycle_cnt + 16'd1;endelsecycle_cnt <= cycle_cnt + 16'd1;endrx_stop:beginif(cycle_cnt == cycle/2 -1)beginrx_state <= rx_data_state;      rx_data <= rx_bits;//latch received datacycle_cnt <= 16'd0;    rx_data_valid <=1'b1;endelsebegin   rx_state <= rx_stop;rx_data_valid <=1'b0;cycle_cnt <= cycle_cnt + 16'd1;endendrx_data_state:begin                   if(rx_data_ready) // 低电平时候,就一直处在则个等待数据接收的状态beginrx_state <= rx_idle;rx_data_valid <=1'b0;endelsebegin                   rx_data_valid <=1'b1;rx_state <= rx_data_state;endenddefault:rx_state <= rx_idle;endcaseend
endendmodule//
//                                                                              //
//                                                                              //
//  Author: meisq                                                               //
//          msq@qq                                                          //
//          ALINX(shanghai) Technology Co.,Ltd                                  //
//          heijin                                                              //
//     WEB: /                                                //
//     BBS: /                                              //
//                                                                              //
//
//                                                                              //
// Copyright (c) 2017,ALINX(shanghai) Technology Co.,Ltd                        //
//                    All rights reserved                                       //
//                                                                              //
// This source file may be used and distributed without restriction provided    //
// that this copyright statement is not removed from the file and that any      //
// derivative work contains the original copyright notice and the associated    //
// disclaimer.                                                                  //
//                                                                              //
////================================================================================
//  Revision History:
//  Date          By            Revision    Change Description
//--------------------------------------------------------------------------------
//2017/8/1                    1.0          Original
//*******************************************************************************/
//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当前状态是stop, 并且此时想要切换到下一个状态,此时,stop, stop 表示停止位。
//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当前状态处在数据的接收一个bit 的过程中。
//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)  // 跟随波特率进行,如果cycle cnt 到达一个周期,这个时候,我们实际上就已经接收了一个bit,此时,我们把接收到bit 个数加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

module uart_tx#( parameter clk_fre = 50,parameter baud_rate = 115200
)
(input clk,input rst_n,input [7:0]tx_data,input tx_data_valid,output tx_pin,output reg tx_data_ready);
//calculates the clock cycle for baud rate 
localparam cycle = clk_fre * 1000000/baud_rate;
parameter s_idle=3'b000;
parameter s_start=3'b001;
parameter s_send_byte=3'b010;
parameter s_stop=3'b011;reg [2:0]state=0;
reg [2:0]next_state;reg [15:0] cycle_cnt=0;
reg [2:0] bit_cnt=0;
reg [7:0] tx_data_latch;
reg tx_reg=1;
assign tx_pin = tx_reg;always@(posedge clk or negedge rst_n)
beginif (rst_n == 1'b0)beginstate <= s_idle;endelse begincase(state)s_idle:beginif(tx_data_valid == 1'b1)beginstate <= s_start;tx_data_latch <= tx_data;tx_data_ready <= 1'b0;endelsebegintx_reg <= 1'b1;state <=s_idle;tx_data_ready <= 1'b1;endends_start:beginif(cycle_cnt == cycle -1)beginstate <= s_send_byte;cycle_cnt <= 16'd0;endelsebegincycle_cnt <= cycle_cnt + 16'd1;tx_reg <= 1'b0;state <= s_start;endends_send_byte:beginif(cycle_cnt == cycle - 1)//分成两种情况,达到8个bit/没到8个字节beginif(bit_cnt == 3'd7)beginstate <= s_stop;bit_cnt <= 3'd0;cycle_cnt <= 16'd0;endelsebeginbit_cnt <= bit_cnt + 3'd1;cycle_cnt <= 16'd0;endendelsebegincycle_cnt <= cycle_cnt + 16'd1;tx_reg = tx_data_latch[bit_cnt];endends_stop:beginif(cycle_cnt == cycle -1)begintx_data_ready <= 1'b1;   state <= s_idle;      cycle_cnt <= 16'd0;    endelsebegin   tx_reg <= 1'b1;cycle_cnt <= cycle_cnt + 16'd1;endenddefault:state <= s_idle;endcaseend
endendmodule

uart_top

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2020/07/31 12:20:32
// Design Name: 
// Module Name: uart_top
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//module uart_top
(
input                           sys_clk_p,         //system clock positive
input                           sys_clk_n,         //system clock negative 
input                           rst_n,             //reset ,low active
input                           uart_rx,           //fpga receive data
output                          uart_tx            //fpga send data
);
parameter                       clk_fre = 200;    //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;          //sending data
reg[7:0]                         tx_str;
reg                              tx_data_valid;    //sending data valid
wire                             tx_data_ready;    //singal for sending data
reg[7:0]                         tx_cnt=0; 
wire[7:0]                        rx_data;          //receiving data
wire                             rx_data_valid;    // receiving data valid
wire                             rx_data_ready;    // singal for receiving data
reg[31:0]                        wait_cnt=0;
reg[3:0]                         state=0;          
wire                             sys_clk;          //single end clock
/*************************************************************************
generate single end clock
**************************************************************************/
IBUFDS sys_clk_ibufgds   
(
.O                      (sys_clk                  ),
.I                      (sys_clk_p                ),
.IB                     (sys_clk_n                )
);
assign rx_data_ready = 1'b1;//always can receive data,//if HELLO ALINX\r\n is being sent, the received data is discarded
/*************************************************************************
1 second sends a packet HELLO ALINX\r\n , FPGA has been receiving state
****************************************************************************/
always@(posedge sys_clk or negedge rst_n)
beginif(rst_n == 1'b0)beginwait_cnt <= 32'd0;tx_data <= 8'd0;state <= IDLE;tx_cnt <= 8'd0;tx_data_valid <= 1'b0;endelsecase(state)IDLE:state <= SEND;SEND:beginwait_cnt <= 32'd0;tx_data <= tx_str;if(tx_data_valid == 1'b1 && tx_data_ready == 1'b1 && tx_cnt < 8'd12)//Send 12 bytes databegintx_cnt <= tx_cnt + 8'd1; //Send data counterendelse if(tx_data_valid && tx_data_ready)//last byte sent is completebegintx_cnt <= 8'd0;tx_data_valid <= 1'b0;state <= WAIT;endelse if(~tx_data_valid)begintx_data_valid <= 1'b1;endendWAIT:beginwait_cnt <= wait_cnt + 32'd1;// 等待1s 数据的时候if(rx_data_valid == 1'b1) // 如果接收到数据begintx_data_valid <= 1'b1; //使得发送数据使能,tx_data <= rx_data;   // send uart received dataendelse if(tx_data_valid && tx_data_ready)begintx_data_valid <= 1'b0;endelse if(wait_cnt >= clk_fre * 1000000) // wait for 1 secondstate <= SEND;enddefault:state <= IDLE;endcase
end
/*************************************************************************
combinational logic  Send "HELLO ALINX\r\n"
****************************************************************************/
always@(*)
begincase(tx_cnt)8'd0 :  tx_str <= "H";8'd1 :  tx_str <= "E";8'd2 :  tx_str <= "L";8'd3 :  tx_str <= "L";8'd4 :  tx_str <= "O";8'd5 :  tx_str <= " ";8'd6 :  tx_str <= "A";8'd7 :  tx_str <= "L";8'd8 :  tx_str <= "I";8'd9 :  tx_str <= "N";8'd10:  tx_str <= "X";8'd11:  tx_str <= "\r";8'd12:  tx_str <= "\n";default:tx_str <= 8'd0;endcase
end
/***************************************************************************
calling uart_tx module and uart_rx module
****************************************************************************/
uart_rx#
(
.clk_fre(clk_fre),
.baud_rate(115200)
) uart_rx_inst
(
.clk                        (sys_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                        (sys_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

实验结果

仿真结果

仿真代码

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2020/08/01 10:50:48
// Design Name: 
// Module Name: vtl_uart_rx_test
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//module vtl_uart_rx_test;
wire sys_clk_n;
reg sys_clk_p;
reg rst_n;
reg uart_rx;
wire uart_tx;uart_top  uart_test(.sys_clk_p(sys_clk_p),.sys_clk_n(sys_clk_n),.rst_n(rst_n),.uart_rx(uart_rx),.uart_tx(uart_tx)
);parameter bps_115200 = 86800;
parameter send_data = 8'b1010_0011;
integer i=0;initial beginsys_clk_p =0;#100;rst_n = 0;#100;rst_n =1;#100;uart_rx = 1'b1;#10000;uart_rx = 1'b0;for(i =0;i<8;i=i+1)#bps_115200 uart_rx = send_data[i];#bps_115200 uart_rx = 1'b0;#bps_115200 uart_rx = 1'b1;;#2000000; endalways #25 sys_clk_p <=~sys_clk_p; //此时的频率是200Massign sys_clk_n = ~sys_clk_p;endmodule

上电测试

总结

相对全面的了解了FPGA中的串口的协议,以及fpga基本状态机的编写的过程,能否相对更加有经验的调试自己所编写的fpga 的程序。

更多推荐

4、vivado之uart串口数据发送与接收

本文发布于:2024-03-08 08:45:43,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1720377.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:串口   数据   vivado   uart

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!