uart协议:它为总线的一个接口,只有两个引脚----(rx与tx)接受的引脚和发送的引脚。总线发送和接受都只能是1bit的数据。因此 ,它为串转并—在转串。下面是它的时序图:
uart_rx :
接受模块按照上图分为以下部分;
一 , 空闲部分:
它在接受完一个字节(8bit)后,变为空闲部分,等待着发送。
二 ,开始部分:
在上图可以看出,在start之前,有一个下降沿。这个下降沿就是判断接受的一个标志。这个地方用到了以前的沿检测的知识。并且,这个start要持续一个字节的时间。
三,接受部分:
在开始之后,就到了接受的部分,在接受完之后,有一个停止标志位,这个标志被拉高之后,就开始发送。
rx 模块设计:
首先我们要用到一个辅助工具——串口小助手,来帮助我们完成这次的实验。而串口小助手我们可以要将它的波特率与clk要一致。所以,我们先用一个模块来放置它的分频。二,因为在有判断到下降沿,它才开始工作,所以,有一个模块为沿检测模块。三,在接受字符的时候,我们用状态机转换它的接受,所以,我们在用一个模块来放转移状态的信号。四,就是它的状态模块。因为一个字节为8bit,每次只能接受1bit,所以,先分成8个状态,又因为开始与初始的纠缠,又想一想,离不开它们的帮助,所以,又增加两个状态。最终,我们在状态模块分成10个状态。(在模块中用热码表示)下面,我们写一写它的状态图:
uart_tx:
发送模块:它与接受模块大体一致,但是有几处不一样的地方。第一,因为在接受完之后我们才开始发送。所以 ,我们在每接受完一个字节后有一个接收完毕后的信号,这个信号是发送的开始。然后在发送的状态模块里,应该要有一个拉低的过程,因为接受方要检测到上升沿。
/// 问题:
第一 :在状态图中出现的错误较多,一般在状态模块中,状态是一个状态结束之后在转移下一状态的。所以,在写的时候,没有必要将分频段的计数与上。
第二:在判断下降沿的时候,因为它是接受的开始,有可能会发生一个字节里有好几个下降沿,这时候会影响状态转移。所以,我们在设计一个计数器,记下降沿的。在接收完毕后清零,然后其他计数在下降沿开始,并且它是第一个下降沿的时候,开始从零计数,这样就不会影响状态转移。
第三:我们在每个状态中间接受bit,这样会较稳定点。
第四:在停止信号,我们也将它设计在停止状态的中间,这样可以发送多个字节时候不会出现乱码。
//
uart_rx :
pll后的计数模块(pll分频之后的为5M,波特率为9600)
`module bavt(
input clk,
input rst_n,
input neg,
input [3:0]NBR,
output [11:0]cot_o
);
reg [11:0]cot;
parameter M=520;
always@(posedge clk or negedge rst_n )
begin
if(~rst_n)
cot<=12'b0;
else if(neg==1'b1 && NBR==1)
cot<=12'b0;
else if(cot==M-1 )
cot<=12'b0;
else
cot<=cot+1'b1;
end
assign cot_o=cot;
endmodule`
沿检测
module judge_length(
input clk,
input rst_n,
input number_o,
input clk_rx,
input [11:0]cot_o,
output reg [3:0]NBR,
output reg neg,
output reg start_o
);
wire neg_o;
reg [1:0]number;
parameter M=520;
always@(posedge clk or negedge rst_n)
begin
if(~rst_n)
number<=2'b11;
else
begin
number[0]<=number_o;
number[1]<=number[0];
end
end
assign neg_o=(~number[0]) & number[1];
always@(posedge clk)
be