FPGA-based adaptive serial communication (Auto Baud Rate)

Do class-based, equivalent to review it again verilog.


Achieved

1. The receiving end of the fixed pattern: 8N1 ​​BAUD: 921600.

2. The transmitting end 8N1, any baud rate (not take the extreme values).

3. The digital display baud rate (hexadecimal).

 

used

1. overnight visit.

2.ego1 platform + usb2uart.


 

Overall block diagram

Tx the input signal through a frequency acquisition layer count value at 100Mhz, to the baud rate generating layer obtained receiving layer baud rate.

Receiving layer receives the serial data to the FIFO layer , layer FIFO serial transmission layer based on feedback data sent FIFO.

Transmitting a fixed layer data sent to the PC 921600 baud. In order to achieve the baud rate swap.

 


 

Frequency trap layer algorithm

1.uart agreement

Here we consider only the most commonly used 8N1, i.e., 8 data bits, no parity, 1 stop bit.

The rising edge of the clock line, tx and maintained until the falling edge of the line a rising edge that is a start bit. Then 8 data bits (LSB first). 10 and then to the high level stop bit.

It is worth mentioning that, tx line will not return to the original level after a certain level, for example, on a data bit is low, or low current position will not change back to high and then low after the end of the data bits.

What is the impact? If tx send 0xff, then there is only a low-level pulse! That is the start bit pulse width.

2. Algorithms

 Hit two beats, clock synchronization and filter out spikes. Considering the data signal input mostly ascii.

We find a most special from the inside, U, this character is binary 10101010, plus the beginning of the end of the bit line level to the tx:

0101010101, there are four or five level pulse width, which is the ideal situation. Such pulse width is measured out of the baud rate.

However, if a general character, transmitting a plurality of low-level pulse bytes may obtain, from the smallest to find the most likely there is the baud rate (the minimum possible level pulse width is the minimum baud rate multiple).

所以我们的算法就是多次测频率,从里面找一个最小的,即认为是波特率。注意这里的频率,波特率都是相对于ego1的100Mhz时钟,并不需要化为实际波特率。

程序

 1 `timescale 1ns / 1ps
 2 
 3 
 4 module cap_freqence(
 5             input        clk,
 6             input        rst_n,
 7             input         freq_in,
 8             input         cap_en,
 9             output     freq_cap//27bit 0-134,217,727 对输入信号波特率测得的频率            
10     );
11 reg[26:0]  freq_cap = 14'd10416;    //rst ??????
12 reg[26:0] tmp_cap,sequence_cap[2:0];    //cap 5 times and Use the smallest one as baud
13 reg [2:0] cap_cnt;
14 // reg cap_finish;
15 reg s0_RS_232_RX,s1_RS_232_RX;        //同步寄存器,消除亚稳态
16 reg tmp0_RS_232_RX,tmp1_RS_232_RX;    //数据寄存器,移位寄存器
17 reg cap_state;                        //0:idle 1:work
18 wire neg_RX;//下降沿
19 always@(posedge clk or negedge rst_n)//同步寄存器,消除亚稳态
20     if(!rst_n)
21         begin
22             s0_RS_232_RX <= 1'b0;
23             s1_RS_232_RX <= 1'b0;    
24         end
25     else 
26         begin
27             s0_RS_232_RX <= freq_in;   //次态
28             s1_RS_232_RX <= s0_RS_232_RX;//现态
29         end
30 always@(posedge clk or negedge rst_n)//数据寄存器
31     if(!rst_n)
32         begin
33             tmp0_RS_232_RX <= 1'b0;
34             tmp1_RS_232_RX <= 1'b0;    
35         end
36     else 
37         begin
38             tmp0_RS_232_RX <= s1_RS_232_RX;
39             tmp1_RS_232_RX <= tmp0_RS_232_RX;    
40         end
41 //共打两拍再检测输入脚
42 assign neg_RX = (!tmp0_RS_232_RX) & tmp1_RS_232_RX;//下降沿检测
43 
44 always@(posedge clk or negedge rst_n)//cap工作状态
45     if(!rst_n)begin
46         cap_state <= 0;
47         end
48     else if(neg_RX)                    //下降沿开始测频
49         cap_state <= 1; 
50     else if (tmp0_RS_232_RX)        //高电平退出测频
51         cap_state <= 0; 
52 
53 always@(posedge clk or negedge rst_n)//以100Mhz时钟测输入引脚低电平脉宽
54     if(!rst_n)
55         begin
56             tmp_cap <= 27'd0;
57             
58         end
59     else if(cap_state)                //串口工作状态(接受)时计数
60         begin
61             if(tmp0_RS_232_RX)        //计完一次频率
62                 begin
63                    sequence_cap[cap_cnt] <= tmp_cap;
64                    tmp_cap <= 27'd0;
65                    cap_cnt <= cap_cnt + 1;//0 1 2 3,4测完4次后为4
66                 end
67             else
68                tmp_cap <= tmp_cap + 1'b1; 
69         end
70         
71 integer i;
72 reg[26:0] min_cap;
73 
74 always@(cap_cnt)                    //测完一个序列便从测频序列里找出最小脉宽即为bps
75     begin
76         if (cap_cnt == 2'd5)
77             begin
78                 min_cap=sequence_cap[0];//1st one as minimal cap
79                 for (i=1;i<5;i=i+1)
80                     if (sequence_cap[i] < min_cap)
81                         if (sequence_cap[i] > 10)
82                             min_cap = sequence_cap[i];
83                 if (cap_en)            //手动控制更新baud
84                     freq_cap = min_cap;
85             end
86     end
87     
88 endmodule

这个程序有瑕疵,用了初始化。不懂

freq_cap
这个变量放在rst里面复位后,之后都不能被下面
freq_cap = min_cap;
这句更新,暂时这么写吧!


效果

Guess you like

Origin www.cnblogs.com/katachi/p/10962505.html