?? rxd.v
字號(hào):
/*
自己編寫(xiě)的串口UART的接收程序,在工程應(yīng)用中測(cè)試通過(guò)。
支持中斷和查詢模式,基本的設(shè)計(jì)思路是:先用比波特率高16倍的速率檢測(cè)串行輸入數(shù)據(jù),
如果檢測(cè)到連續(xù)的低電平,則認(rèn)為收到了起始位,接著按照波特率的速率,檢測(cè)輸入串行數(shù)據(jù),
完成指定位數(shù)的數(shù)據(jù)接收后,將數(shù)據(jù)鎖存在輸出鎖存器中(這樣有一個(gè)字節(jié)的數(shù)據(jù)緩沖能力,同樣也可以將數(shù)據(jù)寫(xiě)入外部的FIFO),
并且產(chǎn)生中斷信號(hào)。
該設(shè)計(jì)對(duì)串行輸入信號(hào)的畸變(經(jīng)過(guò)光耦或線路的傳輸電容較大)的情況均能較好的適應(yīng)。
由于是初學(xué)Verilog時(shí)編寫(xiě)的,條理和移植性較差,但總算能正確運(yùn)行,希望批評(píng)指正。liyzz99@163.com。
*/
module uart_rx(clk,txd,rd,check,outd,int);
input clk; 輸入時(shí)鐘60mhz
input txd; 輸入串行線
input rd; 讀取接收到的數(shù)據(jù),高有效,讀取數(shù)據(jù)會(huì)使outd[9]位自動(dòng)清零
input check; 查詢是否有數(shù)據(jù)接收到 在outd[9]位檢測(cè),為“1”時(shí)有數(shù)據(jù)到。
output [9:0]outd; 輸出數(shù)據(jù)
output int; 中斷輸出
reg [9:0]d; 內(nèi)部數(shù)據(jù)暫存
wire bps; 波特率計(jì)數(shù)溢出線
reg [3:0]bps_cnt; 波特率計(jì)數(shù)器
reg [8:0]start_check; 起始位檢測(cè)移位器
reg start; 起始位有效標(biāo)記
reg [9:0]shift; 串并轉(zhuǎn)換移位器
reg [2:0]rd_clr; rd信號(hào)下沿延時(shí)
reg [3:0]bit_cnt; 接收到的數(shù)據(jù)位計(jì)數(shù)器
wire clr_out; rd信號(hào)下沿后的清零信號(hào)
reg [6:0]s; 16倍波特率的時(shí)鐘計(jì)數(shù)器。
wire xx; 16倍波特率的時(shí)鐘計(jì)數(shù)器溢出信號(hào)
wire end_rxd;
assign xx = (s[6]&s[5]&s[0])?1:0; /*(0x61+1) = 97 = 60,000,000/38400/16 */
assign bps = (bps_cnt[3]&bps_cnt[2]&bps_cnt[1]&bps_cnt[0]&xx);
assign end_rxd = bit_cnt[3]&bit_cnt[0]&bps; /*8bit data 2bit stop,如果沒(méi)有校驗(yàn)位,則需要將個(gè)數(shù)減小到9位*/
assign clr_out = (~rd_clr[2]&rd_clr[1]);
assign outd = (rd|check)?d:10'bzzzzzzzzzz;
assign int = ~d[9];
always @(posedge(clk))
begin
rd_clr <= rd_clr<<1;
rd_clr[0] <= rd;
if(clr_out)
d[9] <= 0; //清楚數(shù)據(jù)接收好標(biāo)記
else
begin
if(end_rxd)
begin
d[0] <= shift[8];
d[1] <= shift[7];
d[2] <= shift[6];
d[3] <= shift[5];
d[4] <= shift[4];
d[5] <= shift[3];
d[6] <= shift[2];
d[7] <= shift[1];
d[8] <= shift[0]; //這位是校驗(yàn)位,也可以將校驗(yàn)的結(jié)果直接鎖存在這一位。
d[9] <= 1;
/*
如果沒(méi)有校驗(yàn)位,則程序變?yōu)椤? d[0] <= shift[7];
d[1] <= shift[6];
d[2] <= shift[5];
d[3] <= shift[4];
d[4] <= shift[3];
d[5] <= shift[2];
d[6] <= shift[1];
d[7] <= shift[0];
d[8] <= 0;
d[9] <= 1;
*/
end
end
if(xx | ~start&txd)
s <= 0;
else
begin
s <= s+1;
end
if(~start)
bps_cnt <=0;
else
begin
if(xx)
bps_cnt <= bps_cnt+1;
end
if(end_rxd)
begin
start_check <=0;
start <=0;
end
else
begin
if(xx)
begin
start_check <= start_check<<1;
start_check[0] <= ~txd;
start <=(start|(~start_check[8]&start_check[7]
&start_check[6]&start_check[5]
&start_check[4]&start_check[3]
&start_check[2]&start_check[1]
&start_check[0]));
end
end
if(~start)
bit_cnt <=0;
else
begin
if(bps)
bit_cnt <= bit_cnt+1;
end
if(bps)
begin
shift <= shift<<1;
shift[0] <= txd;
end
end
endmodule
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -