微电子学院电子科学与技术刘源1120162371 11111601时间:2018年7月UART串口模块设计一.设计要求1.uart模块由tx发送部分和rx接受部分两部分以及对应的时钟分频模块构成。
2.按照如图数据流,tx将8bit并行数据转为串行数据发送至rx模块,rx模块接收后校验并8bit并行输出。
tx要有对应的状态标志位(如:ready,buzy),rx要有校验标志(如:error)。
3.要求8bit并行数据和uart串行数据的带宽均为9600bps,rx接收模块要求以16倍频重采样接收。
4.Uart数据格式:1位起始位,8位数据位,先发高位,后发低位,1位偶校验,1位停止位。
二、仿真要求1.编写testbench进行仿真。
2.通过读文件的方式,在仿真中输入多组(三组以上)数据。
3.观察uart串口数据及接收数据。
三、设计过程设计问题列表:实现过程问题列表:仿真问题列表:结果:期望传输的数据:波形结果:data:将mem储存到data。
wrsig:标志数据读入tx模块的结束。
mem:希望传输的数据。
i:mem的地址。
j:指示读入数据的结束。
send:指示uarttx模块处于并行转串行状态。
datain:数据输入到uarttx中了。
tx:uarttx输出的串行数据。
Idle:指示uarttx模块是否在工作。
Presult:校验码。
rx:uartrx接受的串行数据。
dataout:最终输出的并行数据结果。
(将data的毛刺波形进行了消除)data:uartrx输出的并行数据。
rdsig:指示上个数据发送结束。
dataerror:校验码检验结果。
frameerro:帧检验结果。
receive:指示uartrx处于工作状态。
presult:根据接受到的rx得出的校验码结果。
Debug:由于我对软件和语法不是很熟,在编的过程中很多报错信息没有心情截图保留,一心只想快点解决问题,再加上问题一个接一个,完全没有考虑好好记录下报错信息。
但当我认真的把一个个错误都解决了、搞懂了,我发现大部分错误都是我不熟悉语法和软件导致,熟悉了以后反而忘了当时是怎么搞错的。
但我仍是总结了一些我自己以后需要注意的地方。
1.模块实例化时,要记得结束时加分号。
2.模块中要用的变量要在前面进行声明。
3.过程赋值只能在initial和always语句中进行。
4.If语句里不能嵌套always块。
5.要给给每个量赋初值,尤其是用到计数时。
6.从模块内部来看,模块的输入变量要用wire型,输出可以wire也可以reg。
但从外部来看,输入给一个模块的变量可以是reg也可以是wire,但从模块里输出的只能是wire。
7.仿真模块的module括号里什么也不写,换句话说没有输入输出。
在其中实例化顶层文件就可把激励发送给各模块。
8.读写函数的地址要用/隔开。
9.Memery型变量的地址可以用reg型变量来控制。
参考资料网址:https:///view/4008d94aba1aa8114531d921https:///course/UESTC-1002525007https:///dreamdonghui/article/details/76343438https:///sinat_25887055/article/details/52503180https:///nkthinker/article/details/4255358https:///a8039974/article/details/38796237/article/201310/184677.htmlhttps:///moon9999/article/details/69450912/god_like_donkey/archive/2009/10/28/159119 2.htmlhttps:///tianxingzhexxxx/article/details/40536857https:///Times_poem/article/details/52036592代码:1.顶层模块module uart(clk,data,wrsig); //顶层模块。
input clk;input [7:0]data;input wrsig;clk_div a3(.clk(clk),.clkout(clkout));uarttx a1(.clk(clkout),.datain(data),.wrsig(wrsig),.tx(tx),.idle(idle));uartrx a2(.rx(tx),.clk(clkout),.rdsig(rdsig),.dataout(dataout),.dataerro(dataerro),.frameerro(frameerro));endmodule2.时钟分频模块://我用的50MHZ频率时钟,为了9600波特率和16倍重采样,分频系数应该为326.module clk_div(clk,clkout );input clk;output clkout;reg clkout;reg [15:0]count;initial begincount<=16'd0;clkout<=1'b0;endalways @(posedge clk)beginif(count==16'd162)beginclkout<=1'b1;count<=count+16'd1;endelse if(count==16'd325)beginclkout<=1'b0;count<=16'd0;endelse count<=count+16'd1;endendmodule3.发送模块:module uarttx(clk,datain,wrsig,idle,tx);input clk;input [7:0] datain;input wrsig; //指示仿真模块一个数据开始接收。
output idle; //指示模块处于工作状态。
output tx;reg send;wire clk;wire [7:0]datain;wire wrsig;reg tx;reg idle;reg presult; //校验码reg [7:0] count;parameter paritymode=1'b0; //改变初值可以改变奇校验或偶校验。
always @(posedge wrsig) begin //来检测仿真模块的上一个数据是否传输完毕。
if ( ~idle) //如果该模块空闲,就开始发送。
send<=1'b1;endalways @(posedge clk) beginif(count==8'd168) //发送完一帧数据。
send<=1'b0;endalways@(posedge clk) beginif(send==1'b1) begin //当该模块处于发送状态时,用来判断状态,决定发送哪个数据。
case(count)8'd0:begintx<=1'b0; //发送起始位。
idle<=1'b1;count<=count+8'd1;end8'd16:begintx<=datain[7]; //发送第一位。
presult<=datain[7]^paritymode; //校验码。
idle<=1'b1;count<=count+8'd1;end8'd32:begintx<=datain[6]; //第二位。
presult<=datain[6]^presult;idle<=1'b1;count<=count+8'd1;end8'd48:begin //第三位。
tx<=datain[5];presult<=datain[5]^presult;idle<=1'b1;count<=count+8'd1;end8'd64:begintx<=datain[4];presult<=datain[4]^presult;idle<=1'b1;count<=count+8'd1;end8'd80:begintx<=datain[3];presult<=datain[3]^presult;idle<=1'b1;count<=count+8'd1;end8'd96:begintx<=datain[2];presult<=datain[2]^presult;idle<=1'b1;count<=count+8'd1;end8'd112:begintx<=datain[1];presult<=datain[1]^presult;idle<=1'b1;count<=count+8'd1;end8'd128:begintx<=datain[0];presult<=datain[0]^presult;idle<=1'b1;count<=count+8'd1;end8'd144:begintx<=presult; //发送校验位。
presult<=datain[7]^paritymode; //该校验位传给下一组数据。
继续以上步骤。
idle<=1'b1;count<=count+8'd1;end8'd160:begintx<=1'b1; //发送停止位。
idle<=1'b1;count<=count+8'd1;end8'd168:begintx<=1'b1;idle<=1'b0; //标志一帧发送完毕。
count<=count+8'd1;enddefault:begincount<=count+8'd1;endendcaseendelse begin //没有处于发送状态。
tx<=1'b1;count<=8'd0;idle<=1'b0;endendendmodule4.接收模块:module uartrx(clk,rx,dataout,rdsig,dataerro,frameerro);input clk;input rx; //输入的串行数据output rdsig; //来标志一帧数据输出的完毕。