久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

RS232 波特率時(shí)鐘產(chǎn)生方法?

 aixuexidewau1 2019-09-04

目錄

方法一

方法二

波特率參數(shù)化產(chǎn)生方法


上篇博文介紹了:RS232接口是如何工作的,?

講到了該接口的傳輸速率,,也就是波特率可以為:

  • 1200 bauds.

  • 9600 bauds.

  • 38400 bauds.

  • 115200 bauds (usually the fastest you can go).

在這里,我們希望以最大速度使用串行鏈路,,即115200波特(較慢的速度也很容易生成),。 FPGA通常以MHz速度運(yùn)行,遠(yuǎn)高于115200Hz(按照今天的標(biāo)準(zhǔn),,RS-232相當(dāng)慢),。 我們需要找到一種方法來(lái)生成(從FPGA時(shí)鐘)一個(gè)“tick”,盡可能接近每秒115200次,。

產(chǎn)生波特率的方法可以分為兩種,,原理近似:

方法一


傳統(tǒng)上,RS-232芯片使用1.8432MHz時(shí)鐘,,因?yàn)檫@樣可以非常容易地生成標(biāo)準(zhǔn)波特頻率...... 1.8432MHz除以16得到115200Hz,。

可以以下面的方法來(lái)分頻得到分頻時(shí)鐘(波特率時(shí)鐘):

  1. // let's assume the FPGA clock signal runs at 1.8432MHz
  2. // we create a 4-bit counter
  3. reg [3:0] BaudDivCnt;
  4. always @(posedge clk) BaudDivCnt <= BaudDivCnt + 1; // count forever from 0 to 15
  5. // and a tick signal that is asserted once every 16 clocks (so 115200 times a second)
  6. wire BaudTick = (BaudDivCnt==15);

那很簡(jiǎn)單,。 但是,如果不是1.8432MHz,,你有2MHz的時(shí)鐘怎么辦,? 要從2MHz時(shí)鐘產(chǎn)生115200Hz,我們?nèi)钥梢圆捎梅诸l的方法,,但是這里的分頻會(huì)產(chǎn)生誤差,,盡管如此,這是FPGA所容許的,。

2000_000/115200=17.361111111111111111111111111111

可以采用17分頻的方法來(lái)產(chǎn)生這樣的波特率,。

采用Verilog描述:

  1. module baud_gen_n17d(
  2. input clk,
  3. input enable,
  4. output reg BaudTick = 0
  5. );
  6. reg [4:0] baud_count = 0;
  7. /* always@(posedge clk) begin
  8. if(enable && baud_count < 16) begin
  9. baud_count <= baud_count + 1;
  10. BaudTick <= 0;
  11. end
  12. else if(enable && baud_count == 16) begin
  13. baud_count <= 0;
  14. BaudTick <= 1;
  15. end
  16. else ;
  17. end */
  18. always@(posedge clk) begin
  19. if(enable) begin
  20. if(baud_count < 16) begin
  21. baud_count <= baud_count + 1;
  22. BaudTick <= 0;
  23. end
  24. else if(baud_count == 16) begin
  25. baud_count <= 0;
  26. BaudTick <= 1;
  27. end
  28. else ;
  29. end
  30. else ;
  31. end
  32. endmodule

Testbench文件為:

  1. module baud_gen_f17_tb(
  2. );
  3. reg enable;
  4. reg clk;
  5. wire Baud_Tick;
  6. initial begin
  7. clk = 0;
  8. forever
  9. # 250 clk = ~clk;
  10. end
  11. initial enable = 1;
  12. baud_gen_n17d u0(
  13. .clk(clk),
  14. .enable(1'b1),
  15. .BaudTick(Baud_Tick)
  16. );
  17. endmodule

仿真波形為:

從仿真波形中可以看出,傳輸一位數(shù)據(jù)需要8.75us,,那么傳輸10bit數(shù)據(jù)需要87.5us,;

如果波特率為標(biāo)準(zhǔn)的115200的話,那么傳輸1bit數(shù)據(jù)需要8.68us,,那么傳輸10bit數(shù)據(jù)需要86.8us,;

二者誤差相差0.7us;

如果采用標(biāo)準(zhǔn)波特率的話,,一位停止位就占了8.68us,,這點(diǎn)誤差算的了什么呢?況且RS232接收數(shù)據(jù)采用過(guò)采樣,,所以,,不必?fù)?dān)心采用分頻時(shí)鐘生成的波特率不準(zhǔn)確的問(wèn)題。

下面是請(qǐng)教前輩的聊天記錄:

有這樣的前輩,,耐心的教我這個(gè)菜鳥(niǎo),還真是很感動(dòng)呢,!


方法二

前面方法一是一種常規(guī)意義上的分頻而已,,沒(méi)有那么多的花里胡哨,也很好理解,,但是在我們的主要參考鏈接中給出了另外一種方法,,鏈接:Baud generator

還以2MHz的系統(tǒng)時(shí)鐘為例,要產(chǎn)生115200的波特率時(shí)鐘,。

前面我們算過(guò)二者的比率為:2000000/115200=17.361111111111111111111111111111,;

文中的思路是:

期望2000000是2的冪。 顯然2000000不是,。 所以我們改變比率...而不是“2000000/115200”,,讓我們使用“1024/59”= 17.356。 這非常接近我們的理想比率,,并且實(shí)現(xiàn)了高效的FPGA實(shí)現(xiàn):我們使用增量為59的10位累加器,,每次累加器溢出時(shí)都會(huì)標(biāo)記一個(gè)Tick,。

這是個(gè)什么原理呢?

通過(guò)比率相似,,我們可以取一個(gè)計(jì)數(shù)器,,位數(shù)恰好能計(jì)數(shù)到1024,那么選一個(gè)10位的計(jì)數(shù)器(實(shí)際上是11位,,后面解釋?zhuān)?,累加器每次累?9,會(huì)發(fā)現(xiàn)計(jì)數(shù)到第17個(gè)59時(shí),,累加器溢出,,溢出一個(gè)時(shí)鐘,這樣我們可以取溢出位為T(mén)ick,,這樣就實(shí)現(xiàn)了計(jì)數(shù)17,,Tick就有效一次,和17分頻原理一致呀,。

這種方法的要點(diǎn)在于,,我們需要找到一個(gè)2的冪次的分子,來(lái)湊出相似比率,。

當(dāng)然,,如果你忘記了這種方法,還可以直接用方法一,,也即是直接分頻的方法,。

下面對(duì)這種方法進(jìn)行仿真:


以FPGA系統(tǒng)時(shí)鐘為2MHz為例,

Verilog描述代碼:

  1. module BaudGen(
  2. input clk,
  3. input enable,
  4. output BaudTick
  5. );
  6. // let's assume the FPGA clock signal runs at 2.0000MHz
  7. // we use a 10-bit accumulator plus an extra bit for the accumulator carry-out
  8. reg [10:0] acc = 0; // 11 bits total!
  9. // add 59 to the accumulator at each clock
  10. always @(posedge clk) begin
  11. if(enable)
  12. acc <= acc[9:0] + 59; // use 10 bits from the previous accumulator result, but save the full 11 bits result
  13. else
  14. acc <= 59;
  15. end
  16. assign BaudTick = acc[10]; // so that the 11th bit is the accumulator carry-out
  17. endmodule

testbench文件:

  1. module BaudGen_tb(
  2. );
  3. reg clk;
  4. wire BaudTick;
  5. initial begin
  6. clk = 0;
  7. forever
  8. #250 clk = ~clk;
  9. end
  10. BaudGen u_BaudGen(
  11. .clk(clk),
  12. .enable(1'b1),
  13. .BaudTick(BaudTick)
  14. );
  15. endmodule

仿真波形為:

看細(xì)節(jié):

計(jì)數(shù)值超過(guò)1024后,,最高位變?yōu)?,,同時(shí)BaudTick變?yōu)楦唠娖剑掷m(xù)時(shí)間為一個(gè)時(shí)鐘周期,。

通過(guò)下圖計(jì)算下傳輸1bit數(shù)據(jù)需要多久:

經(jīng)過(guò)簡(jiǎn)單計(jì)算,,需要8.5us傳輸1bit,那么1s中傳輸多少位呢,?1000000/8.5=117647;

然后我們算算誤差多大:(117647 - 115200)/115200 = 0.02,;可見(jiàn)誤差很小。

前面方法一也說(shuō)了,,這種誤差我們完全可以接受,。


波特率參數(shù)化產(chǎn)生方法

由于前面已經(jīng)鋪墊過(guò)了,所以這種參數(shù)化完全是套用下參數(shù)而已,,直接引用鏈接:https://www./SerialInterface2.html

參數(shù)化FPGA波特率發(fā)生器

之前的設(shè)計(jì)使用的是10位累加器,,但隨著時(shí)鐘頻率的增加,需要更多的位。

這是一個(gè)25MHz時(shí)鐘和16位累加器的設(shè)計(jì),。 設(shè)計(jì)參數(shù)化,,易于定制。

parameter ClkFrequency = 25000000; // 25MHz
parameter Baud = 115200;
parameter BaudGeneratorAccWidth = 16;
parameter BaudGeneratorInc = (Baud<<BaudGeneratorAccWidth)/ClkFrequency;

reg [BaudGeneratorAccWidth:0] BaudGeneratorAcc;
always @(posedge clk)
  BaudGeneratorAcc <= BaudGeneratorAcc[BaudGeneratorAccWidth-1:0] + BaudGeneratorInc;

wire BaudTick = BaudGeneratorAcc[BaudGeneratorAccWidth];

最后一個(gè)實(shí)現(xiàn)問(wèn)題:“BaudGeneratorInc”計(jì)算錯(cuò)誤,,因?yàn)閂erilog使用32位中間結(jié)果,,計(jì)算超出了這個(gè)。 更改以下行以獲得解決方法,。

parameter BaudGeneratorInc = ((Baud<<(BaudGeneratorAccWidth-4))+(ClkFrequency>>5))/(ClkFrequency>>4);

此行還具有對(duì)結(jié)果進(jìn)行舍入而不是截?cái)嗟母郊觾?yōu)勢(shì),。

現(xiàn)在我們擁有足夠精確的波特率發(fā)生器,我們可以繼續(xù)使用RS-232發(fā)送器和接收器模塊,。


最后一個(gè)參數(shù)化還是會(huì)讓人產(chǎn)生疑惑的,,算了還是直接用自己的方法吧,花里胡哨的:

  1. module BaudGen_param(
  2. input clk,
  3. input enable,
  4. output BaudTick
  5. );
  6. parameter ClkFrequency = 25000000; // 25MHz
  7. parameter Baud = 115200;
  8. parameter Ratio = ClkFrequency/Baud;
  9. parameter BaudGeneratorAccWidth = 16;
  10. parameter BaudGeneratorInc = (1<<BaudGeneratorAccWidth)/Ratio;
  11. reg [BaudGeneratorAccWidth:0] BaudGeneratorAcc = 0;
  12. always @(posedge clk)
  13. if(enable)
  14. BaudGeneratorAcc <= BaudGeneratorAcc[BaudGeneratorAccWidth-1:0] + BaudGeneratorInc;
  15. else
  16. BaudGeneratorAcc <= BaudGeneratorInc;
  17. assign BaudTick = BaudGeneratorAcc[BaudGeneratorAccWidth];
  18. endmodule

測(cè)試文件為:

  1. module BaudGen_Param_tb;
  2. reg clk;
  3. wire BaudTick;
  4. initial begin
  5. clk = 0;
  6. forever
  7. #20 clk = ~clk;
  8. end
  9. BaudGen_param u0(
  10. .clk(clk),
  11. .enable(1'b1),
  12. .BaudTick(BaudTick)
  13. );
  14. endmodule

行為仿真波形圖:

可見(jiàn),,波特周期是8.68us,,與115200的波特率對(duì)應(yīng)的波特周期差不多。

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購(gòu)買(mǎi)等信息,,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請(qǐng)點(diǎn)擊一鍵舉報(bào),。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類(lèi)似文章 更多