<SPAN style=
"FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体"
>
module
bps_gen(clk,
rst_n,
bps_clk);
input
clk;
input
rst_n;
output
reg
bps_clk;
reg
[8:0]cnt;
always
@(
posedge
clk
or
negedge
rst_n)
//波特率时钟产生,采用9600bps
if
(~rst_n)
begin
cnt<=0;
bps_clk<=0;
end
//16倍波特率时钟,bps=9600bit/s;
else
//1bit=>1000000/9.6=10416ns
if
(cnt==162)
//104166ns/period20ns=5208个clk
begin
//uart时钟采用16倍波特率时钟
cnt<=0;
//5208/16=325
bps_clk<=~bps_clk;
//每162个clk计数bps_clk取反
end
else
cnt<=cnt+1;
endmodule
module
uart_tx( rst_n,
bps_clk_tx,
txd,
enable,
tx_din);
input
rst_n;
input
bps_clk_tx;
input
enable;
input
[7:0] tx_din;
output
reg
txd;
reg
[3:0] tx_cnt;
reg
[3:0] bps_cnt;
always
@(
posedge
bps_clk_tx)
if
(~rst_n||(~enable)) bps_cnt<=0;
else
if
(bps_cnt<
4'd15
)
bps_cnt<=bps_cnt+1;
//每16个波特率时钟记一次数,到15归零
else
bps_cnt<=0;
//在下面的接收模块没有这样处理,直接每次加16
always
@(
posedge
bps_clk_tx
or
negedge
rst_n)
//异步复位
if
(~rst_n)
begin
tx_cnt<=0;
txd<=
1'b1
;
//复位的时候TXD给1
end
//
else
if
(~enable)
//在没有发送信号时回到复位状态
begin
tx_cnt<=0;
txd<=
1'b1
;
end
else
begin
//下面用7看下面所记述的第二种联方式会理解
if
(bps_cnt==
4'd7
)
//这个数字开始写的15 为了同步接收模块改成7
if
(tx_cnt<
4'd10
)
tx_cnt<=tx_cnt+1;
//每16个bps_clk加一
else
tx_cnt<=0;
case
(tx_cnt)
1:txd<=
1'b0
;
//发送起始位
2:txd<=tx_din[0];
//先发送第0位
3:txd<=tx_din[1];
4:txd<=tx_din[2];
5:txd<=tx_din[3];
6:txd<=tx_din[4];
7:txd<=tx_din[5];
8:txd<=tx_din[6];
9:txd<=tx_din[7];
10:txd<=
1'b1
;
//发送停止位,无效验位
default
: ;
endcase
end
endmodule
module
uart_rx( rst_n,
bps_clk_rx,
rxd,
rx_dout,
rx_start);
//接收开始信号
input
rst_n;
input
rxd;
input
bps_clk_rx;
output
[7:0] rx_dout;
output
reg
rx_start;
reg
rxd_reg;
reg
[7:0] cnt;
reg
[7:0] data_int;
reg
start_flag;
wire
start;
assign
start=~rxd&rxd_reg;
//下降沿信号
always
@(
posedge
bps_clk_rx)
//D触发器检测检测下降沿
if
(~rst_n) rxd_reg<=0;
//为了更稳定的信号,可以用两级或三级触发器
else
rxd_reg<=rxd;
always
@(*)
if
(~rst_n||(cnt==
8'd143
)) start_flag<=
1'b0
;
//cnt=143数据已经发送完毕,拉低开始信号
else
if
(start) start_flag<=
1'b1
;
//第一个下降沿信号是起始信号
//这里不用else用以记忆开始信号标志
always
@(
posedge
bps_clk_rx)
if
(~rst_n||~start_flag)
//复位,如果用异步复位这里要分开写
begin
data_int<=
8'hzz
;
cnt<=0;
rx_start<=0;
end
else
begin
rx_start<=1;
//开始接收
if
(cnt==
8'd143
)
cnt<=0;
else
cnt<=cnt+1;
case
(cnt)
'd23:data_int[0]<=rxd;
'd39:data_int[1]<=rxd;
'd55:data_int[2]<=rxd;
'd71:data_int[3]<=rxd;
'd87:data_int[4]<=rxd;
'd103:data_int[5]<=rxd;
'd119:data_int[6]<=rxd;
'd135:data_int[7]<=rxd;
default
:;
endcase
end
assign
rx_dout=data_int;
//把这个改成reg型写到data_int[7]收完之后
endmodule
</SPAN>