send <= 1'b0; end end
always @(posedge clk) begin
if(send == 1'b1)
begin
case(cnt) //产生起始位 8'd0: begin tx <= 1'b0; idle <= 1'b1; cnt <= cnt + 8'd1; end
8'd16: begin
tx <= datain[0]; //发送数据0位 presult <= datain[0]^paritymode; idle <= 1'b1; cnt <= cnt + 8'd1; end
8'd32: begin
tx <= datain[1]; //发送数据1位 presult <= datain[1]^presult; idle <= 1'b1;
cnt <= cnt + 8'd1;
end 8'd48: begin
tx <= datain[2]; //发送数据2位 presult <= datain[2]^presult; idle <= 1'b1;
cnt <= cnt + 8'd1; end 8'd64:
begin
tx <= datain[3]; //发送数据3位 presult <= datain[3]^presult; idle <= 1'b1; cnt <= cnt + 8'd1; end 8'd80: begin
tx <= datain[4]; //发送数据4位 presult <= datain[4]^presult; idle <= 1'b1;
cnt <= cnt + 8'd1; end 8'd96:
begin
tx <= datain[5]; //发送数据5位 presult <= datain[5]^presult; idle <= 1'b1; cnt <= cnt + 8'd1; end
8'd112: begin
tx <= datain[6]; //发送数据6位 presult <= datain[6]^presult; idle <= 1'b1;
cnt <= cnt + 8'd1; end 8'd128:
begin
tx <= datain[7]; //发送数据7位 presult <= datain[7]^presult; idle <= 1'b1;
cnt <= cnt + 8'd1; end 8'd144:
begin
tx <= presult; //发送奇偶校验位 presult <= datain[0]^paritymode; idle <= 1'b1;
cnt <= cnt + 8'd1; end 8'd160:
begin
tx <= 1'b1; //发送停止位 idle <= 1'b1; cnt <= cnt + 8'd1; end 8'd176: begin
tx <= 1'b1;
idle <= 1'b0; //一帧资料发送结束 cnt <= cnt + 8'd1;
end
default: begin
cnt <= cnt + 8'd1; end endcase end else begin tx <= 1'b1; cnt <= 8'd0; idle <= 1'b0; end end endmodule
为了测试UART发送模块的正确性,需要编写一个测试模块来测试UART发送模块, Verilog HDL语言代码如下:
module testuart(clk, dataout, wrsig); input clk;
output[7:0] dataout; output wrsig;
reg [7:0] dataout; reg wrsig; reg [7:0] cnt;
always @(posedge clk) begin
if(cnt == 254) begin
dataout <= dataout + 8'd1; //每次数据加“1” wrsig <= 1'b1; //产生发送命令 cnt <= 8'd0; end else begin
wrsig <= 1'b0; cnt <= cnt + 8'd1; end end
endmodule
将发送模块和测试模块生成原理图模块和频率长生模块连接成发送模块电路图,如下图4:
得到的仿真图如下图5
波形仿真报告说明:
对图,当发送命令wrsig的上升沿有效时,启动发送数据。串行数据的波形与发送数据dataout相一致,UART的发送模块得到正确验证。
4.3 UART的接收模块
UART接收模块的功能:时时检测线路,当线路产生下降沿时,即认为线路有数据传输,启动接收数据进程进行接收,按从低位到高位接收数据。UART接收模块的Verilog HDL语言代码如下:
module uartrx(clk, rx, dataout, rdsig, dataerror, frameerror); input clk; //采样时钟
input rx; //UART数据输入 output dataout; //接收数据输出
output rdsig;
output dataerror; //资料出错指示 output frameerror; //帧出错指示 reg[7:0] dataout; reg rdsig, dataerror; reg frameerror; reg [7:0] cnt;
reg rxbuf, rxfall, receive;
parameter paritymode = 1'b0;
reg presult, idle;
always @(posedge clk) //检测线路的下降沿 begin
rxbuf <= rx;
rxfall <= rxbuf & (~rx); end
always @(posedge clk)
begin
if (rxfall && (~idle)) //检测到线路的下降沿并且原先线路为空闲,启动接收数据进程 begin
receive <= 1'b1;
end
else if(cnt == 8'd175) //接收数据完成 begin
receive <= 1'b0; end
end
always @(posedge clk) begin
if(receive == 1'b1) begin case (cnt) 8'd0:
begin
idle <= 1'b1; cnt <= cnt + 8'd1; rdsig <= 1'b0;
end
8'd24: //接收第0位数据 begin idle <= 1'b1; dataout[0] <= rx;
presult <= paritymode^rx; cnt <= cnt + 8'd1; rdsig <= 1'b0;