串口接收
串口帧
设计文件
`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 2023/01/12 23:11:28
// Design Name:
// Module Name: UART_Byte_Rx
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//module UART_Byte_Rx#(parameter BaudRate = 115200,//波特率parameter ClockRate = 50_000_000//系统时钟)
(Clk,Rst_n,Rx,Rx_Data,Rx_Done
);input Clk;input Rst_n;input Rx;output reg [7:0] Rx_Data;output Rx_Done;//设置波特率 将一bit时间分成16份,在每一份的中间进行采样localparam Buad_Num = ClockRate/BaudRate/16;//检测下降沿reg [2:0] neg_edge_r;wire neg_edge_flag;always@(posedge Clk or negedge Rst_n)beginif(!Rst_n)neg_edge_r<=3'b0;elseneg_edge_r<={neg_edge_r[1:0],Rx};endassign neg_edge_flag=neg_edge_r[2:1]==2'b10;//接收使能信号reg rx_en;always@(posedge Clk or negedge Rst_n)beginif(!Rst_n)rx_en<=0;else if(neg_edge_flag)rx_en<=1'd1;else if(Rx_Done)rx_en<=1'd0;elserx_en<=rx_en;end//波特率计数reg [12:0] buad_cnt;wire add_buad_cnt;wire end_buad_cnt;always@(posedge Clk or negedge Rst_n)beginif(!Rst_n)buad_cnt<=0;else if(add_buad_cnt)beginif(end_buad_cnt)buad_cnt<=0;else buad_cnt<=buad_cnt+1'b1;endelsebuad_cnt<=0;endassign add_buad_cnt=rx_en;assign end_buad_cnt=buad_cnt>=(Buad_Num-1'd1);//采样点wire buad_cnt_middle=buad_cnt==(Buad_Num/2);//计数采样次数 16*10reg [7:0] sampling_cnt;wire add_sampling_cnt;wire end_sampling_cnt;always@(posedge Clk or negedge Rst_n)beginif(!Rst_n)sampling_cnt<=0;else if(rx_en)beginif(add_sampling_cnt)beginif(end_sampling_cnt)sampling_cnt<=0;else sampling_cnt<=sampling_cnt+1'b1;end endelsesampling_cnt<=0;endassign add_sampling_cnt=buad_cnt_middle;assign end_sampling_cnt=add_sampling_cnt && sampling_cnt>=159;//设置存储数据的寄存器//8个寄存器,每个寄存器的位宽是3(原因是:16次采集,我们选择中间的7次采集,进行相加,结果大于4[100]的,认为是高电平)reg [2:0]rx_data_r[7:0];reg [2:0]sta_bit;//起始位reg [2:0]sto_bit;//停止位//0 【0】 1 【1】 2 【2】 3 【3】 4 【4】 5 【5】 6 【6】 7 【7】 8 【8】 9 【9】 10 【10】 always@(posedge Clk or negedge Rst_n)beginif(!Rst_n)beginrx_data_r[0]<=0;rx_data_r[1]<=0;rx_data_r[2]<=0;rx_data_r[3]<=0;rx_data_r[4]<=0;rx_data_r[5]<=0;rx_data_r[6]<=0;rx_data_r[7]<=0;sta_bit<=0;sto_bit<=0;endelse if(buad_cnt_middle)begincase(sampling_cnt)0:begin//清0所有寄存器rx_data_r[0]<=0;rx_data_r[1]<=0;rx_data_r[2]<=0;rx_data_r[3]<=0;rx_data_r[4]<=0;rx_data_r[5]<=0;rx_data_r[6]<=0;rx_data_r[7]<=0;sta_bit<=0;sto_bit<=0;end5,6,7,8,9,10,11: sta_bit <= sta_bit + Rx;21,22,23,24,25,26,27: rx_data_r[0] <= rx_data_r[0] + Rx;37,38,39,40,41,42,43: rx_data_r[1] <= rx_data_r[1] + Rx;53,54,55,56,57,58,59: rx_data_r[2] <= rx_data_r[2] + Rx;69,70,71,72,73,74,75: rx_data_r[3] <= rx_data_r[3] + Rx;85,86,87,88,89,90,91: rx_data_r[4] <= rx_data_r[4] + Rx;101,102,103,104,105,106,107: rx_data_r[5] <= rx_data_r[5] + Rx;117,118,119,120,121,122,123: rx_data_r[6] <= rx_data_r[6] + Rx;133,134,135,136,137,138,139: rx_data_r[7] <= rx_data_r[7] + Rx;149,150,151,152,153,154,155: sto_bit <= sto_bit + Rx;default:;endcaseendend//将读取的数据反馈回来 4=3'b100always@(posedge Clk or negedge Rst_n)beginif(!Rst_n)Rx_Data<=0;else if(sampling_cnt==159)beginRx_Data[0]<=(rx_data_r[0][2]);Rx_Data[1]<=(rx_data_r[1][2]);Rx_Data[2]<=(rx_data_r[2][2]);Rx_Data[3]<=(rx_data_r[3][2]);Rx_Data[4]<=(rx_data_r[4][2]);Rx_Data[5]<=(rx_data_r[5][2]);Rx_Data[6]<=(rx_data_r[6][2]);Rx_Data[7]<=(rx_data_r[7][2]);endendassign Rx_Done=end_sampling_cnt;endmodule
仿真验证
`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 2023/01/12 23:13:05
// Design Name:
// Module Name: UART_Byte_Rx_tb
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//module UART_Byte_Rx_tb();reg Clk;reg Rst_n;reg Rx;wire [7:0] Rx_Data;wire Rx_Done;UART_Byte_Rx UART_Byte_Rx(Clk,Rst_n,Rx,Rx_Data,Rx_Done);initial Clk=1;always #10 Clk=~Clk;initial beginRst_n=0;Rx=1;#201Rst_n=1;#200;uart_tx_byte(8'h5a); #9000;uart_tx_byte(8'h88); #9000;uart_tx_byte(8'h11);#9000;$stop;endtask uart_tx_byte;input [7:0]tx_data;beginRx=1;#20;Rx=0;#8680;Rx=tx_data[0];#8680;Rx=tx_data[1];#8680;Rx=tx_data[2];#8680;Rx=tx_data[3];#8680;Rx=tx_data[4];#8680;Rx=tx_data[5];#8680;Rx=tx_data[6];#8680;Rx=tx_data[7];#8680;Rx=1;#8680;endendtaskendmodule
串口发送
**注意:**电平信号的传输线中有一个参考电平线(一般是GND),然后信号线上的信号值是由信号线电平和参考电平线的电压差决定。所以我们一定要养成模块之间共地的好习惯。
串口帧
模块设计
设计文件
`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 2023/01/06 11:30:58
// Design Name:
// Module Name: UART_Byte_Tx
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//module UART_Byte_Tx#(parameter BaudRate = 115200,//波特率parameter ClockRate = 50_000_000//系统时钟)
(Clk,Rst_n,Send_En,data_byte,Tx_Data,Tx_Done,uart_state
);input Clk;input Rst_n;input Send_En;input [7:0] data_byte;output reg Tx_Data;output reg Tx_Done;output reg uart_state;//设置使能reg tx_en;always@(posedge Clk or negedge Rst_n)beginif(!Rst_n)tx_en<=0;else if(Send_En)tx_en<=1'd1;else if(Tx_Done)tx_en<=1'd0;elsetx_en<=tx_en;end//设置波特率localparam Buad_Num = ClockRate/BaudRate;//设置计数器reg [12:0] buad_cnt;wire add_buad_cnt;wire end_buad_cnt;always@(posedge Clk or negedge Rst_n)beginif(!Rst_n)buad_cnt<=0;else if(add_buad_cnt)beginif(end_buad_cnt)buad_cnt<=0;else buad_cnt<=buad_cnt+1'b1;endelsebuad_cnt<=0;endassign add_buad_cnt=tx_en;assign end_buad_cnt=buad_cnt>=(Buad_Num-1'd1);//设置发送bit计数reg [3:0] bit_cnt;wire add_bit_cnt;wire end_bit_cnt;always@(posedge Clk or negedge Rst_n)beginif(!Rst_n)bit_cnt<=0;else if(add_bit_cnt)bit_cnt<=bit_cnt+1'd1;else if(end_bit_cnt)bit_cnt<=0;elsebit_cnt<=bit_cnt;endassign add_bit_cnt=buad_cnt==1;assign end_bit_cnt=(bit_cnt==4'd10 && add_bit_cnt) || !tx_en;//发送数据always@(posedge Clk or negedge Rst_n)beginif(!Rst_n)Tx_Data<=1;else begincase(bit_cnt)4'd1:Tx_Data<=0;4'd2:Tx_Data<=data_byte[0];4'd3:Tx_Data<=data_byte[1];4'd4:Tx_Data<=data_byte[2];4'd5:Tx_Data<=data_byte[3];4'd6:Tx_Data<=data_byte[4];4'd7:Tx_Data<=data_byte[5];4'd8:Tx_Data<=data_byte[6];4'd9:Tx_Data<=data_byte[7];4'd10:Tx_Data<=1;default:Tx_Data<=1;endcaseendend//发送结束always@(posedge Clk or negedge Rst_n)beginif(!Rst_n)Tx_Done<=0;else if(bit_cnt==4'd10 && add_bit_cnt)Tx_Done<=1;elseTx_Done<=0;end//发送状态(有效数据)wire En_uart_state;wire Nen_uart_state;always@(posedge Clk or negedge Rst_n)beginif(!Rst_n)uart_state<=0;else if(En_uart_state)uart_state<=1;else if(Nen_uart_state)uart_state<=0;endassign En_uart_state=bit_cnt==4'd1 && add_bit_cnt;assign Nen_uart_state=bit_cnt==4'd9 && add_bit_cnt;endmodule
仿真验证
`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 2023/01/06 11:31:09
// Design Name:
// Module Name: UART_Byte_Tx_tb
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//module UART_Byte_Tx_tb();reg Clk;reg Rst_n;reg Send_En;reg [7:0]data_byte;wire Tx_Data;wire Tx_Done;wire uart_state;initial Clk=1;always #10 Clk=~Clk;initial beginRst_n=0;Send_En=0;data_byte=0;#201;Rst_n=1;data_byte=8'b1001_0110;Send_En=1;#20;Send_En=0;#100000;data_byte=8'b0111_0110;Send_En=1;#20;Send_En=0;#100000;$stop;endUART_Byte_Tx UART_Byte_Tx(.Clk(Clk),.Rst_n(Rst_n),.Send_En(Send_En),.data_byte(data_byte),.Tx_Data(Tx_Data),.Tx_Done(Tx_Done),.uart_state(uart_state));endmodule
串口接收-串口发送
基于串口的数据收、发模块,使用收、发模块,完成串口数据回环实验。
RTL视图
设计文件
`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 2023/01/12 23:49:51
// Design Name:
// Module Name: UART_Data_Loopback_top
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//module UART_Data_Loopback_top(Clk,Rst_n,Rx,Tx_Data);input Clk;input Rst_n;input Rx;output Tx_Data;//串口接收wire [7:0] Rx_Data;wire Rx_Done;UART_Byte_Rx#(115200,50_000_000)UART_Byte_Rx(.Clk(Clk),.Rst_n(Rst_n),.Rx(Rx),.Rx_Data(Rx_Data),.Rx_Done(Rx_Done));//串口发送wire Tx_Done;wire uart_state;UART_Byte_Tx#(115200,50_000_000)UART_Byte_Tx(.Clk(Clk),.Rst_n(Rst_n),.Send_En(Rx_Done),.data_byte(Rx_Data),.Tx_Data(Tx_Data),.Tx_Done(Tx_Done),.uart_state(uart_state));endmodule
约束文件
set_property PACKAGE_PIN Y18 [get_ports Clk]
set_property PACKAGE_PIN A21 [get_ports Rst_n]
set_property PACKAGE_PIN M15 [get_ports Tx_Data]
set_property IOSTANDARD LVCMOS33 [get_ports Clk]
set_property IOSTANDARD LVCMOS33 [get_ports Rst_n]
set_property IOSTANDARD LVCMOS33 [get_ports Tx_Data]set_property PACKAGE_PIN J21 [get_ports Rx]
set_property IOSTANDARD LVCMOS33 [get_ports Rx]
板级验证
任意字节发送
设计文件
`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 2023/01/13 10:16:15
// Design Name:
// Module Name: UART_Bytes_Tx
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//module UART_Bytes_Tx#(parameter BaudRate = 115200,//波特率parameter ClockRate = 50_000_000,//系统时钟parameter BytesNum=5//发送字节个数)
(Clk,Rst_n,Trans_Go,data_bytes,Tx_Data,Trans_Done,uart_state
);localparam Bit_Wide = BytesNum * 8;input Clk;input Rst_n;input Trans_Go;input [Bit_Wide-1:0] data_bytes;output Tx_Data;output reg Trans_Done;output uart_state;//发送使能reg Trans_en;always@(posedge Clk or negedge Rst_n)beginif(!Rst_n)Trans_en<=0;else if(Trans_Go)Trans_en<=1;else if(Trans_Done)Trans_en<=0;elseTrans_en<=Trans_en;end//计数已经发送的字节数reg [5:0] send_byte_num;//最多可发送63字节,想要发送更多字节,需要调大位宽wire add_send_byte_num;always@(posedge Clk or negedge Rst_n)beginif(!Rst_n)send_byte_num<=0;else if(Trans_en) beginif(add_send_byte_num)send_byte_num<=send_byte_num+1'b1;elsesend_byte_num<=send_byte_num;endelse send_byte_num<=0;endassign add_send_byte_num=Tx_Done;//将传输的值寄存到寄存器中,每发送一个字节进行移位reg [Bit_Wide-1:0] data_bytes_r;always@(posedge Clk or negedge Rst_n)beginif(!Rst_n)data_bytes_r<=0;else if(Trans_Go)data_bytes_r<=data_bytes;else if(Tx_Done)data_bytes_r<=data_bytes_r>>8;elsedata_bytes_r<=data_bytes_r;end//将多字节数据分成一字节发送,使用发送结束标志位来启动下一次发送reg [7:0] data_byte_temp;always@(posedge Clk or negedge Rst_n)beginif(!Rst_n)data_byte_temp<=0;else data_byte_temp<=data_bytes_r;end//串口单字节发送wire Tx_Done;wire uart_state;reg Send_En;always@(posedge Clk or negedge Rst_n)beginif(!Rst_n)Send_En<=0;else if( ( Trans_Go || Tx_Done ) && !(send_byte_num>=BytesNum-1 && add_send_byte_num) )Send_En<=1;else Send_En<=0;endUART_Byte_Tx#(115200,50_000_000)UART_Byte_Tx(.Clk(Clk),.Rst_n(Rst_n),.Send_En(Send_En),.data_byte(data_byte_temp),.Tx_Data(Tx_Data),.Tx_Done(Tx_Done),.uart_state(uart_state));//全部字节发送标志位always@(posedge Clk or negedge Rst_n)beginif(!Rst_n)Trans_Done<=0;else if(send_byte_num>=BytesNum-1 && add_send_byte_num)Trans_Done<=1;else Trans_Done<=0;endendmodule
仿真验证
`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 2023/01/13 10:24:58
// Design Name:
// Module Name: UART_Bytes_Tx_tb
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//module UART_Bytes_Tx_tb();reg Clk;reg Rst_n;reg Trans_Go;reg [39:0]data_bytes;wire Tx_Data;wire Trans_Done;wire uart_state;initial Clk=1;always #10 Clk=~Clk;initial beginRst_n=0;Trans_Go=0;data_bytes=0;#201;Rst_n=1;data_bytes=40'h123456789a;Trans_Go=1;#20;Trans_Go=0;@(posedge Trans_Done);#200000data_bytes=40'ha987654321;Trans_Go=1;#20;Trans_Go=0;@(posedge Trans_Done);#200000data_bytes=40'habcdef4321;Trans_Go=1;#20;Trans_Go=0;@(posedge Trans_Done);#200000$stop;endUART_Bytes_Tx#(.BytesNum(5))UART_Bytes_Tx(.Clk(Clk),.Rst_n(Rst_n),.Trans_Go(Trans_Go),.data_bytes(data_bytes),.Tx_Data(Tx_Data),.Trans_Done(Trans_Done),.uart_state(uart_state));endmodule
按键发送多字节
发送AMH\r\n
RTL视图
设计文件
`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 2023/01/13 15:09:15
// Design Name:
// Module Name: UART_Bytes_Tx_test
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//module UART_Bytes_Tx_test(Clk,Rst_n,Key_in,Tx_Data
);input Clk;input Rst_n;input Key_in;output Tx_Data;//按键输入wire Key_flag;wire Key_State;key_filter key_filter(.Clk(Clk),.Rst_n(Rst_n),.Key_in(Key_in),.Key_flag(Key_flag), //按键按下标志位.Key_State(Key_State) //高电平,按键按下);//任意字节发送wire [39:0] data_bytes;assign data_bytes=40'h0A0D484D41;// AMH/r/nwire Trans_Done;wire uart_state;UART_Bytes_Tx#(.BytesNum(5))UART_Bytes_Tx(.Clk(Clk),.Rst_n(Rst_n),.Trans_Go(Key_flag),.data_bytes(data_bytes),.Tx_Data(Tx_Data),.Trans_Done(Trans_Done),.uart_state(uart_state));endmodule
约束文件
set_property PACKAGE_PIN Y18 [get_ports Clk]
set_property PACKAGE_PIN A21 [get_ports Rst_n]
set_property PACKAGE_PIN M15 [get_ports Tx_Data]
set_property IOSTANDARD LVCMOS33 [get_ports Clk]
set_property IOSTANDARD LVCMOS33 [get_ports Rst_n]
set_property IOSTANDARD LVCMOS33 [get_ports Tx_Data]set_property PACKAGE_PIN B21 [get_ports Key_in]
set_property IOSTANDARD LVCMOS33 [get_ports Key_in]