FPGA实现串口接收
功能实现:所有的疑惑都在注释中有解释!
`timescale 1ns / 1ps ////////////////////////////////////////////////////////////////////////////////// // Company: // Engineer: // // Create Date: 14:26:20 01/04/2022 // Design Name: // Module Name: uart_rx_01 // Project Name: // Target Devices: // Tool versions: // Description: // // Dependencies: // // Revision: // Revision 0.01 - File Created // Additional Comments: // ////////////////////////////////////////////////////////////////////////////////// //设计思想如下: //传输的数据里面包含:一个起始位,八个数据位,一个停止位 //每一个传输位:分为十六个采集数据点,每个数据采集点在其片段的中点位置,十六位中取其中七位为有效采集数据位前五后四不取,将其中七位数据位进行计算得出来该位为高还是低 module uart_rx_01( clk, Reset_n, uart_rx, Bund_set, Data, Rx_Done ); input clk; input Reset_n; input uart_rx; input [2:0]Bund_set; output reg [7:0]Data; output reg Rx_Done; reg [1:0] uart_rx_r; always@(posedge clk)begin uart_rx_r[0] <= uart_rx; uart_rx_r[1] <= uart_rx_r[0]; end wire pedge_uart_rx;//上升沿 //assign pedge_uart_rx = ((uart_rx_r[1] == 0) && (uart_rx_r[0] == 1)) //与下面的功能类似 assign pedge_uart_rx = (uart_rx_r == 2'b01); wire nedge_uart_rx;//下降沿 assign nedge_uart_rx = (uart_rx_r == 2'b10); //下降沿作为分频计数的开始 reg RX_EN; always@(posedge clk or negedge Reset_n) if(!Reset_n) RX_EN <= 0; else if(nedge_uart_rx) //一开始理解有问题,觉得其他的数据中可能存在下降沿会影响RX_EN的使能,多虑了。只需要控制好RX_EN置为0的条件就ok RX_EN <= 1; else if(Rx_Done || (sta_bit >= 4)) //数据发送结束或者(起始位传输不对,错误的起始位) RX_EN <= 0; //基本的分频计数器 reg [8:0] div_cnt; always@(posedge clk or negedge Reset_n) if(!Reset_n) div_cnt <= 0; else if(RX_EN)begin if(div_cnt == bund_dr - 1) div_cnt <= 0; else div_cnt <= div_cnt + 1'b1; end else div_cnt <= 0; //波特率转换为计数值门限 reg [8:0] bund_dr; always@(*) //1000000000为一秒钟, 16是将每个数据分为16个采集点, 20为每个时钟周期为20ns case(Bund_set) 0: bund_dr <= 1000000000/16/20/9600; 1: bund_dr <= 1000000000/16/20/19200; 2: bund_dr <= 1000000000/16/20/38400; 3: bund_dr <= 1000000000/16/20/57600; 4: bund_dr <= 1000000000/16/20/115200; default: bund_dr <= 1000000000/16/20/9600; endcase //每次什么时候进行采集样本,发出一个上升沿信号 wire bps_clk_16x; assign bps_clk_16x = (div_cnt == (bund_dr - 1) /2); //二级计数器,计数采集样本的总次数(十个数据需要总共160次) reg[7:0] bps_cnt; always@(posedge clk or negedge Reset_n) if(!Reset_n) bps_cnt <= 0; else if(RX_EN)begin if(bps_clk_16x)begin if(bps_cnt == 160) bps_cnt <= 0; else bps_cnt <= bps_cnt + 1'b1; end else bps_cnt <= bps_cnt; end else bps_cnt <= 0; reg [3:0]data_r[7:0]; reg [3:0]sta_bit; reg [3:0]sto_bit; always@(posedge clk or negedge Reset_n) if(!Reset_n)begin sta_bit <= 0; data_r[0] <= 0; data_r[1] <= 0; data_r[2] <= 0; data_r[3] <= 0; data_r[4] <= 0; data_r[5] <= 0; data_r[6] <= 0; data_r[7] <= 0; sto_bit <= 0; end else if(bps_clk_16x)begin case(bps_cnt) 0:begin sta_bit <= 0; data_r[0] <= 0; data_r[1] <= 0; data_r[2] <= 0; data_r[3] <= 0; data_r[4] <= 0; data_r[5] <= 0; data_r[6] <= 0; data_r[7] <= 0; sto_bit <= 0; end 5,6,7,8,9,10,11: sta_bit <= sta_bit + uart_rx; 21,22,23,24,25,26,27:data_r[0] <= data_r[0] + uart_rx; 37,38,39,40,41,42,43:data_r[1] <= data_r[1] + uart_rx; 53,54,55,56,57,58,59:data_r[2] <= data_r[2] + uart_rx; 69,70,71,72,73,74,75:data_r[3] <= data_r[3] + uart_rx; 85,86,87,88,89,90,91:data_r[4] <= data_r[4] + uart_rx; 101,102,103,104,105,106,107:data_r[5] <= data_r[5] + uart_rx; 117,118,119,120,121,122,123:data_r[6] <= data_r[6] + uart_rx; 133,134,135,136,137,138,139:data_r[7] <= data_r[7] + uart_rx; 149,150,151,152,153,154,155: sto_bit <= sto_bit + uart_rx; default:; endcase end //将数据输出到Data上,进行判断,判断其七次累加的结果 always@(posedge clk or negedge Reset_n) if(!Reset_n) Data <= 0; else if(bps_clk_16x && (bps_cnt == 160))begin Data[0] <= (data_r[0] >= 4)? 1'b1:1'b0; Data[1] <= (data_r[1] >= 4)? 1'b1:1'b0; Data[2] <= (data_r[2] >= 4)? 1'b1:1'b0; Data[3] <= (data_r[3] >= 4)? 1'b1:1'b0; Data[4] <= (data_r[4] >= 4)? 1'b1:1'b0; Data[5] <= (data_r[5] >= 4)? 1'b1:1'b0; Data[6] <= (data_r[6] >= 4)? 1'b1:1'b0; Data[7] <= (data_r[7] >= 4)? 1'b1:1'b0; end //Rx_Done信号的处理 always@(posedge clk or negedge Reset_n) if(!Reset_n) Rx_Done <= 0; else if((div_cnt == (bund_dr - 1)/2) && (bps_cnt == 160)) Rx_Done <= 1; else Rx_Done <= 0; endmodule
测试激励
`timescale 1ns / 1ps //////////////////////////////////////////////////////////////////////////////// // Company: // Engineer: // // Create Date: 21:30:47 01/05/2022 // Design Name: uart_rx_01 // Module Name: E:/FPGA_WORKSPACE/uart_rx/uart_rx_01_test.v // Project Name: uart_rx // Target Device: // Tool versions: // Description: // // Verilog Test Fixture created by ISE for module: uart_rx_01 // // Dependencies: // // Revision: // Revision 0.01 - File Created // Additional Comments: // //////////////////////////////////////////////////////////////////////////////// module uart_rx_01_test; // Inputs reg clk; reg Reset_n; reg uart_rx; wire [2:0] Bund_set; // Outputs wire [7:0] Data; wire Rx_Done; assign Bund_set = 4; // Instantiate the Unit Under Test (UUT) uart_rx_01 uut ( .clk(clk), .Reset_n(Reset_n), .uart_rx(uart_rx), .Bund_set(Bund_set), .Data(Data), .Rx_Done(Rx_Done) ); initial clk = 1; always #10 clk = !clk; initial begin // Initialize Inputs Reset_n = 0; uart_rx = 0; // Wait 100 ns for global reset to finish #201; Reset_n = 1; #200; uart_tx_data(8'h5a); @(posedge Rx_Done); #5000; uart_tx_data(8'ha5); @(posedge Rx_Done); #5000; uart_tx_data(8'h56); @(posedge Rx_Done); #5000; // Add stimulus here end task uart_tx_data; input [7:0]tx_data; begin uart_rx = 1; #20; uart_rx = 0; #8680; uart_rx = tx_data[0]; #8680; uart_rx = tx_data[1]; #8680; uart_rx = tx_data[2]; #8680; uart_rx = tx_data[3]; #8680; uart_rx = tx_data[4]; #8680; uart_rx = tx_data[5]; #8680; uart_rx = tx_data[6]; #8680; uart_rx = tx_data[7]; #8680; uart_rx = 1; #8000; end endtask endmodule
`timescale 1ns / 1ps//////////////////////////////////////////////////////////////////////////////////// Company: // Engineer: // // Create Date: 14:26:20 01/04/2022 // Design Name: // Module Name: uart_rx_01 // Project Name: // Target Devices: // Tool versions: // Description: //// Dependencies: //// Revision: // Revision 0.01 - File Created// Additional Comments: ////////////////////////////////////////////////////////////////////////////////////
//设计思想如下://传输的数据里面包含:一个起始位,八个数据位,一个停止位//每一个传输位:分为十六个采集数据点,每个数据采集点在其片段的中点位置,十六位中取其中七位为有效采集数据位前五后四不取,将其中七位数据位进行计算得出来该位为高还是低
module uart_rx_01(clk,Reset_n,uart_rx,Bund_set,Data,Rx_Done ); input clk;input Reset_n;input uart_rx;input [2:0]Bund_set;output reg [7:0]Data;output reg Rx_Done;reg [1:0] uart_rx_r;always@(posedge clk)beginuart_rx_r[0] <= uart_rx;uart_rx_r[1] <= uart_rx_r[0];endwire pedge_uart_rx;//上升沿//assign pedge_uart_rx = ((uart_rx_r[1] == 0) && (uart_rx_r[0] == 1)) //与下面的功能类似assign pedge_uart_rx = (uart_rx_r == 2'b01);wire nedge_uart_rx;//下降沿assign nedge_uart_rx = (uart_rx_r == 2'b10);//下降沿作为分频计数的开始reg RX_EN;always@(posedge clk or negedge Reset_n)if(!Reset_n)RX_EN <= 0;else if(nedge_uart_rx) //一开始理解有问题,觉得其他的数据中可能存在下降沿会影响RX_EN的使能,多虑了。只需要控制好RX_EN置为0的条件就okRX_EN <= 1;else if(Rx_Done || (sta_bit >= 4)) //数据发送结束或者(起始位传输不对,错误的起始位)RX_EN <= 0;//基本的分频计数器reg [8:0] div_cnt;always@(posedge clk or negedge Reset_n)if(!Reset_n)div_cnt <= 0;else if(RX_EN)beginif(div_cnt == bund_dr - 1)div_cnt <= 0;elsediv_cnt <= div_cnt + 1'b1;endelsediv_cnt <= 0;//波特率转换为计数值门限reg [8:0] bund_dr;always@(*) //1000000000为一秒钟, 16是将每个数据分为16个采集点, 20为每个时钟周期为20nscase(Bund_set)0: bund_dr <= 1000000000/16/20/9600;1: bund_dr <= 1000000000/16/20/19200;2: bund_dr <= 1000000000/16/20/38400;3: bund_dr <= 1000000000/16/20/57600;4: bund_dr <= 1000000000/16/20/115200;default: bund_dr <= 1000000000/16/20/9600;endcase//每次什么时候进行采集样本,发出一个上升沿信号wire bps_clk_16x;assign bps_clk_16x = (div_cnt == (bund_dr - 1) /2);//二级计数器,计数采集样本的总次数(十个数据需要总共160次)reg[7:0] bps_cnt;always@(posedge clk or negedge Reset_n)if(!Reset_n)bps_cnt <= 0;else if(RX_EN)beginif(bps_clk_16x)beginif(bps_cnt == 160)bps_cnt <= 0;elsebps_cnt <= bps_cnt + 1'b1;endelsebps_cnt <= bps_cnt;endelsebps_cnt <= 0;reg [3:0]data_r[7:0];reg [3:0]sta_bit;reg [3:0]sto_bit;always@(posedge clk or negedge Reset_n)if(!Reset_n)beginsta_bit <= 0;data_r[0] <= 0;data_r[1] <= 0;data_r[2] <= 0;data_r[3] <= 0;data_r[4] <= 0;data_r[5] <= 0;data_r[6] <= 0;data_r[7] <= 0;sto_bit <= 0;endelse if(bps_clk_16x)begincase(bps_cnt)0:beginsta_bit <= 0;data_r[0] <= 0;data_r[1] <= 0;data_r[2] <= 0;data_r[3] <= 0;data_r[4] <= 0;data_r[5] <= 0;data_r[6] <= 0;data_r[7] <= 0;sto_bit <= 0;end5,6,7,8,9,10,11: sta_bit <= sta_bit + uart_rx;21,22,23,24,25,26,27:data_r[0] <= data_r[0] + uart_rx;37,38,39,40,41,42,43:data_r[1] <= data_r[1] + uart_rx;53,54,55,56,57,58,59:data_r[2] <= data_r[2] + uart_rx;69,70,71,72,73,74,75:data_r[3] <= data_r[3] + uart_rx;85,86,87,88,89,90,91:data_r[4] <= data_r[4] + uart_rx;101,102,103,104,105,106,107:data_r[5] <= data_r[5] + uart_rx;117,118,119,120,121,122,123:data_r[6] <= data_r[6] + uart_rx;133,134,135,136,137,138,139:data_r[7] <= data_r[7] + uart_rx;149,150,151,152,153,154,155: sto_bit <= sto_bit + uart_rx;default:;endcaseend//将数据输出到Data上,进行判断,判断其七次累加的结果always@(posedge clk or negedge Reset_n)if(!Reset_n)Data <= 0;else if(bps_clk_16x && (bps_cnt == 160))beginData[0] <= (data_r[0] >= 4)? 1'b1:1'b0;Data[1] <= (data_r[1] >= 4)? 1'b1:1'b0;Data[2] <= (data_r[2] >= 4)? 1'b1:1'b0;Data[3] <= (data_r[3] >= 4)? 1'b1:1'b0;Data[4] <= (data_r[4] >= 4)? 1'b1:1'b0;Data[5] <= (data_r[5] >= 4)? 1'b1:1'b0;Data[6] <= (data_r[6] >= 4)? 1'b1:1'b0;Data[7] <= (data_r[7] >= 4)? 1'b1:1'b0;end//Rx_Done信号的处理always@(posedge clk or negedge Reset_n)if(!Reset_n)Rx_Done <= 0;else if((div_cnt == (bund_dr - 1)/2) && (bps_cnt == 160))Rx_Done <= 1;elseRx_Done <= 0;endmodule