赞
踩
串口帧
设计文件
`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)begin if(!Rst_n) neg_edge_r<=3'b0; else neg_edge_r<={neg_edge_r[1:0],Rx}; end assign neg_edge_flag=neg_edge_r[2:1]==2'b10; //接收使能信号 reg rx_en; always@(posedge Clk or negedge Rst_n)begin if(!Rst_n) rx_en<=0; else if(neg_edge_flag) rx_en<=1'd1; else if(Rx_Done) rx_en<=1'd0; else rx_en<=rx_en; end //波特率计数 reg [12:0] buad_cnt; wire add_buad_cnt; wire end_buad_cnt; always@(posedge Clk or negedge Rst_n)begin if(!Rst_n) buad_cnt<=0; else if(add_buad_cnt)begin if(end_buad_cnt) buad_cnt<=0; else buad_cnt<=buad_cnt+1'b1; end else buad_cnt<=0; end assign 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*10 reg [7:0] sampling_cnt; wire add_sampling_cnt; wire end_sampling_cnt; always@(posedge Clk or negedge Rst_n)begin if(!Rst_n) sampling_cnt<=0; else if(rx_en)begin if(add_sampling_cnt)begin if(end_sampling_cnt) sampling_cnt<=0; else sampling_cnt<=sampling_cnt+1'b1; end end else sampling_cnt<=0; end assign 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)begin if(!Rst_n)begin 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; end else if(buad_cnt_middle)begin case(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; end 5,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:; endcase end end //将读取的数据反馈回来 4=3'b100 always@(posedge Clk or negedge Rst_n)begin if(!Rst_n) Rx_Data<=0; else if(sampling_cnt==159)begin Rx_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]); end end assign 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 begin Rst_n=0; Rx=1; #201 Rst_n=1; #200; uart_tx_byte(8'h5a); #9000; uart_tx_byte(8'h88); #9000; uart_tx_byte(8'h11); #9000; $stop; end task uart_tx_byte; input [7:0]tx_data; begin Rx=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; end endtask endmodule
**注意:**电平信号的传输线中有一个参考电平线(一般是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)begin if(!Rst_n) tx_en<=0; else if(Send_En) tx_en<=1'd1; else if(Tx_Done) tx_en<=1'd0; else tx_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)begin if(!Rst_n) buad_cnt<=0; else if(add_buad_cnt)begin if(end_buad_cnt) buad_cnt<=0; else buad_cnt<=buad_cnt+1'b1; end else buad_cnt<=0; end assign 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)begin if(!Rst_n) bit_cnt<=0; else if(add_bit_cnt) bit_cnt<=bit_cnt+1'd1; else if(end_bit_cnt) bit_cnt<=0; else bit_cnt<=bit_cnt; end assign 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)begin if(!Rst_n) Tx_Data<=1; else begin case(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; endcase end end //发送结束 always@(posedge Clk or negedge Rst_n)begin if(!Rst_n) Tx_Done<=0; else if(bit_cnt==4'd10 && add_bit_cnt) Tx_Done<=1; else Tx_Done<=0; end //发送状态(有效数据) wire En_uart_state; wire Nen_uart_state; always@(posedge Clk or negedge Rst_n)begin if(!Rst_n) uart_state<=0; else if(En_uart_state) uart_state<=1; else if(Nen_uart_state) uart_state<=0; end assign 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 begin Rst_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; end UART_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)begin if(!Rst_n) Trans_en<=0; else if(Trans_Go) Trans_en<=1; else if(Trans_Done) Trans_en<=0; else Trans_en<=Trans_en; end //计数已经发送的字节数 reg [5:0] send_byte_num;//最多可发送63字节,想要发送更多字节,需要调大位宽 wire add_send_byte_num; always@(posedge Clk or negedge Rst_n)begin if(!Rst_n) send_byte_num<=0; else if(Trans_en) begin if(add_send_byte_num) send_byte_num<=send_byte_num+1'b1; else send_byte_num<=send_byte_num; end else send_byte_num<=0; end assign add_send_byte_num=Tx_Done; //将传输的值寄存到寄存器中,每发送一个字节进行移位 reg [Bit_Wide-1:0] data_bytes_r; always@(posedge Clk or negedge Rst_n)begin if(!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; else data_bytes_r<=data_bytes_r; end //将多字节数据分成一字节发送,使用发送结束标志位来启动下一次发送 reg [7:0] data_byte_temp; always@(posedge Clk or negedge Rst_n)begin if(!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)begin if(!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; end UART_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)begin if(!Rst_n) Trans_Done<=0; else if(send_byte_num>=BytesNum-1 && add_send_byte_num) Trans_Done<=1; else Trans_Done<=0; end endmodule
仿真验证
`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 begin Rst_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); #200000 data_bytes=40'ha987654321; Trans_Go=1; #20; Trans_Go=0; @(posedge Trans_Done); #200000 data_bytes=40'habcdef4321; Trans_Go=1; #20; Trans_Go=0; @(posedge Trans_Done); #200000 $stop; end UART_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/n wire 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]
板级验证
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。