接收模块:
`define VERIFY_EVEN 2'b00
`define VERIFY_ODD 2'b01
`define VERIFY_NONE 2'b10
module uart_rx(
i_clk, //系统时钟输入
i_clk_rx, //移位时钟输入
i_rx_data, //串行数据输入
i_verify_mode,//校验模式(允许:奇校验、偶校验、无校验)输入
i_rst_n, //复位输入
i_ce_n, //允许传输输入
i_clear_int_n,//清除中断输入
o_rx_int, //接收中断输出
o_data , //数据输出,在中断有?时可被读取
o_err //传输出错标志位
);
input i_clk;
input i_clk_rx;
input i_rx_data;
input [1:0] i_verify_mode;
input i_rst_n;
input i_ce_n;
input i_clear_int_n;
output o_rx_int;
output [7:0] o_data;
output o_err;
reg [7:0] r_data;
reg [3:0] r_num;
reg [1:0] r_verify_mode;
reg r_err;
reg r_start;
//写控制寄存器进程,确认何时开启传输
always @(posedge i_clk) begin
if(!i_rst_n | r_err) begin //复位或传输发生错误则终止传输
r_verify_mode <= `VERIFY_NONE;
r_start <= 0;
end else if(i_clk_rx && !i_rx_data && r_num == 0) begin //收到起始位
r_verify_mode <= i_verify_mode ; //每次开始传输的时候确认校验方式
r_start<= 1;
end else if( i_rx_data && //已经收到停止位,停止传输
((r_num == 9 && r_verify_mode == `VERIFY_NONE) ||
(r_num == 10 && (r_verify_mode == `VERIFY_EVEN || r_verify_mode == `VERIFY_ODD) ))
) begin
r_verify_mode <= `VERIFY_NONE;
r_start <= 0;
end
end
//逻辑连接 确定允许传输信号
wire w_start ;
assign w_start = r_start & ~i_ce_n ;
always @ (posedge i_clk) begin
if(!i_rst_n) begin
r_num <= 0;
r_data <= 0;
r_err <= 0;
end else if(w_start && i_clk_rx) begin
r_num <= r_num + 1;
case (r_num)
0 : begin r_data[0] <= i_rx_data ; r_err <= 0 ; end
1 : r_data[1] <= i_rx_data ;
2 : r_data[2] <= i_rx_data ;
3 : r_data[3] <= i_rx_data ;
4 : r_data[4] <= i_rx_data ;
5 : r_data[5] <= i_rx_data ;
6 : r_data[6] <= i_rx_data ;
7 : r_data[7] <= i_rx_data ;
8 : casex(r_verify_mode) //核对校验位、若无校验则直接核对停止位
`VERIFY_EVEN : r_err <= ^r_data ^ i_rx_data ;
`VERIFY_ODD : r_err <= ^r_data ^ i_rx_data ;
`VERIFY_NONE : r_err <= ~ i_rx_data ;
default : r_err <= ~ i_rx_data ;
endcase
9 : r_err <= ~ i_rx_data | r_err ;//检测停止位
endcase
end else if((r_num == 9 && r_verify_mode == `VERIFY_NONE) || //传输完毕
(r_num == 10 && (r_verify_mode == `VERIFY_EVEN || r_verify_mode == `VERIFY_ODD) )) begin
r_num <= 0;
end
end
assign o_err = r_err ;
reg [7:0] r_o_data;
reg r_o_rx_int;
always @ (posedge i_clk) begin
if(!i_rst_n) begin
r_o_data <= 0;
r_o_rx_int <= 0;
end else if((r_num == 9 && r_verify_mode == `VERIFY_NONE) || //传输完毕
(r_num == 10 && (r_verify_mode == `VERIFY_EVEN || r_verify_mode == `VERIFY_ODD) )) begin
if(!r_err) begin
r_o_data <= r_data;
r_o_rx_int <= 1;
end else begin
r_o_data <= 'bz;
r_o_rx_int <= 0;
end
end else if(!i_clear_int_n) begin //手动清除中断标志
r_o_rx_int <= 0;
r_o_data <= 'bz;
end
end
assign o_rx_int = r_o_rx_int ;
assign o_data = r_o_data ;
endmodule
接收模块测试向量:
module uart_rx_tb ;
wire [7:0] o_data ;
wire o_rx_int ;
wire o_err ;
reg i_ce_n ;
reg [1:0] i_verify_mode ;
reg i_clear_int_n ;
reg i_rst_n ;
reg i_clk ;
reg i_rx_data ;
reg i_clk_rx ;
uart_rx
DUT (
.o_data (o_data ) ,
.i_ce_n (i_ce_n ) ,
.i_verify_mode (i_verify_mode ) ,
.o_rx_int (o_rx_int ) ,
.i_clear_int_n (i_clear_int_n ) ,
.i_rst_n (i_rst_n ) ,
.i_clk (i_clk ) ,
.o_err (o_err ) ,
.i_rx_data (i_rx_data ) ,
.i_clk_rx (i_clk_rx ) );
initial begin
i_ce_n = 1 ;
i_clear_int_n = 1;
i_clk = 0;
i_clk_rx = 0;
i_verify_mode = 0 ;
i_rx_data = 0;
i_rst_n = 0;
#200
i_rst_n = 1;
#50
i_verify_mode = 2;
#50
i_ce_n = 0 ;
end
reg [3:0] cnt;
initial cnt = 0;
reg r_tmp;
always @ (negedge i_clk_rx) begin
if(cnt == 0 && !o_err) i_rx_data = 0 ; //发送起始位
else if(cnt>0 && cnt < 9) i_rx_data = ({$random} % 2 )^ r_tmp; //发送随机数据
else if(cnt == 9 || cnt == 10 ) i_rx_data = 1 ; //发送停止位
else i_rx_data = 1 ;//发送空闲位
r_tmp = i_rx_data;
if(cnt <= 20 && !o_err) cnt <= cnt + 1;
else cnt <= 0;
end
//清中断标志位
always @(posedge o_rx_int) begin
#200
i_clear_int_n = 0;
#100
i_clear_int_n = 1;
end
//清错误标志位
always @(posedge o_err) begin
#200
i_rst_n = 0;
#100
i_rst_n = 1;
end
always #50 i_clk = ~ i_clk;
always begin
#400 i_clk_rx = 1;
#100 i_clk_rx = 0;
end
endmodule
接收模块功能仿真波形:
发送模块:
/*
Uart 发送模块
*/
module uart_tx(
i_clk, //系统时钟输入
i_clk_tx, //移位时钟输入
i_data, //数据输入,在i_start_n有效时务必保持稳定
i_verify_mode,//校验模式(允许:奇校验、偶校验、无校验)输入
i_rst_n, //复位输入
i_start_n, //开始传输输入
o_tx_data, //串行数据输出
o_tx_int //发送中断输出
);
input i_clk;
input i_clk_tx;
input i_rst_n;
input i_start_n;
input [7:0] i_data;
input [1:0] i_verify_mode;
output o_tx_data;
output o_tx_int;
`define VERIFY_EVEN 2'b00
`define VERIFY_ODD 2'b01
`define VERIFY_NONE 2'b1x
reg [7:0] r_data;
reg [1:0] r_verify_mode;
reg [3:0] r_num;
reg r_start;
//写内部寄存器进程
//Process generates start signal for transmission
always @(posedge i_clk) begin
if(!i_rst_n) begin
r_data <= 0;
r_start<= 0;
r_verify_mode <= 0;
end else if(!i_start_n) begin
r_data <= i_data;
r_verify_mode <= i_verify_mode;
r_start <= 1;
end else if(r_num == 11) begin
r_start <= 0;
r_verify_mode <= 'bx;
r_data <= 'bx;
end
end
//逻辑连接,在i_start_n 有效电平消失后才产生有效开始信号(开始传输)
//Logic connection ultimate gate signal for transmission start
wire w_start1;
assign w_start1 = r_start & i_start_n ;
//传输数据进程
//Process send data
reg r_o_tx_data;
always @(posedge i_clk) begin
if(!i_rst_n) begin
r_o_tx_data <= 1;
r_num <= 0;
end else if(i_clk_tx && w_start1) begin
r_num <= r_num + 1;
case (r_num)
0 : r_o_tx_data <= 0; //Start bit '0'//发送起始位0
1 : r_o_tx_data <= r_data[0];
2 : r_o_tx_data <= r_data[1];
3 : r_o_tx_data <= r_data[2];
4 : r_o_tx_data <= r_data[3];
5 : r_o_tx_data <= r_data[4];
6 : r_o_tx_data <= r_data[5];
7 : r_o_tx_data <= r_data[6];
8 : r_o_tx_data <= r_data[7];
9 : //发送校验位
casex(r_verify_mode)
`VERIFY_EVEN : r_o_tx_data <= ~^ r_data ; //偶校验 r_data各位同或输出
`VERIFY_ODD : r_o_tx_data <= ^ r_data ; //奇校验 r_data各位异或输出
`VERIFY_NONE : r_o_tx_data <= 1; //无校验 提前发送停止位(仅相当于多消耗1个移位时钟周期)
default : r_o_tx_data <= 1 ;
endcase
10: r_o_tx_data <= 1 ; //End bit '1' //发送停止位1
default : r_o_tx_data <= 1;
endcase
end else if(r_num == 11) r_num <= 0;
end
assign o_tx_data = r_o_tx_data ;
//传输中断产生进程
//Process generates interrupt signal for output
reg r_o_tx_int;
always @(posedge i_clk) begin
if(!i_rst_n || (w_start1 && r_num != 11)) r_o_tx_int <= 0;
else if( w_start1 && r_num == 11) r_o_tx_int <= 1;
end
assign o_tx_int = r_o_tx_int ;
endmodule
发送模块测试向量:
module uart_tx_tb ;
wire o_tx_data ;
wire o_tx_int ;
reg i_clk_tx ;
reg i_rst_n ;
reg [7:0] i_data ;
reg i_clk ;
reg [1:0]i_verify_mode;
reg i_start_n ;
uart_tx
DUT (
.o_tx_int (o_tx_int ) ,
.i_clk_tx (i_clk_tx ) ,
.i_rst_n (i_rst_n ) ,
.i_verify_mode(i_verify_mode),
.i_data (i_data ) ,
.i_clk (i_clk ) ,
.o_tx_data (o_tx_data ) ,
.i_start_n (i_start_n ) );
initial begin
i_rst_n = 0;
i_clk = 0;
i_clk_tx = 0;
i_start_n = 1;
i_verify_mode = 'bz;
i_data = 'bz;
#50
i_data = 8'd125 ;
i_verify_mode = 2'b11;
#400
i_rst_n = 1 ;
#50
i_start_n = 0;
#100
i_start_n = 1;
i_data = 8'bz;
end
//event newtrans;
//always @(posedge i_clk) if(o_tx_int) -> newtrans;
//always @(newtrans) begin
always @ (posedge o_tx_int) begin
#400 ;
i_data = {$random} % 256 ;
i_verify_mode = {$random} % 4;
#50
i_start_n = 0;
#100
i_start_n = 1;
i_data = 8'bz;
end
always #50 i_clk = ~ i_clk;
always begin
#400 i_clk_tx = 1;
#100 i_clk_tx = 0;
end
endmodule
发送模块功能仿真波形:
速度选择模块:
/*
波特率产生公式
Formula generates max cnt for specified bode rate
Fosc = 50MHz
2 * MaxCnt * BodeRate = Fosc
BodeRate MaxCnt HalfCnt
4800 5207 2603
9600 2603 1301
19200 1301 650
115200 216 108
*/
`define PARA_MAXCNT 216
`define PARA_HALFCNT 108
module speedselect (i_ce_n, i_rst_n, i_clk, o_clk);
input i_rst_n;
input i_clk;
input i_ce_n;
output o_clk;
reg [12:0] r_cnt;
always @(posedge i_clk) begin
if(!i_rst_n) begin r_cnt <= 0; end
else if(!i_ce_n) begin
r_cnt <= (r_cnt == `PARA_MAXCNT) ? 0 : r_cnt + 1 ;
end
end
reg r_o_clk;
always @(posedge i_clk) begin
if( i_rst_n &&(!i_ce_n) && r_cnt == `PARA_HALFCNT ) r_o_clk <= 1;
else r_o_clk <= 0;
end
assign o_clk = r_o_clk ;
endmodule
速度选择模块测试向量:
module speedselect_tb ;
wire o_clk ;
reg i_ce_n ;
reg i_clk ;
reg i_rst_n ;
speedselect
DUT (
.o_clk (o_clk ) ,
.i_ce_n (i_ce_n ) ,
.i_clk (i_clk ) ,
.i_rst_n (i_rst_n ) );
initial begin
i_ce_n = 1;
i_clk = 0;
i_rst_n = 0;
#100
i_ce_n = 0;
#100
i_rst_n = 1;
end
always #50 i_clk = ~ i_clk;
endmodule
速度选择模块功能仿真波形: