本文将进入程序设计部分:
第一:时序设计
在进行具体的串口设计之前,先了解通信协议。通常由以下四部分组成,起始位+数据位+校验位+结束位,但是在空闲状态线路上是1,当检测到是0来时就表示数据开始传输了。
话不多说(不懂时序的可以看一下其它博客),直接开始上程序:
下面就是波特率的设置,由于UART是异步串行通信,双方需要约定好时序才可以进行通信。(SPI是同步串行通信,所以在传输的时候会穿CLK)
parameter Start_bit = 1'b0, Stop_bit = 1'b1;
always@(posedge clk or negedge rst_n)
if(!rst_n)
bps_DR <= 16'd5207;//9600
else begin
case(baud_set)
0:bps_DR <= 16'd5207;
1:bps_DR <= 16'd2603;
2:bps_DR <= 16'd1301;
3:bps_DR <= 16'd867;
4:bps_DR <= 16'd433;
default:bps_DR <= 16'd5207;
endcase
end
//Uart波特率的控制,由上面波特率控制计数器决定,整个控制状态都是在传输状态的时候实现(Uart_State= 1 )
always @(posedge clk or negedge rst_n)
if(!rst_n)
Uart_cnt <= 4'd0;
else if(Uart_State)begin
if(Uart_cnt == bps_DR)
Uart_cnt <= 16'd0;
else
Uart_cnt <= Uart_cnt + 1'b1;
end
else
Uart_cnt <= 16'd0;
//下面就是波特率时钟脉冲的产生,因为只能产生一个系统时钟周期的高脉冲,所以可以下面那样写
always @(posedge clk or negedge rst_n)
if(!rst_n)
Uart_clk <= 1'b0;
else if(Uart_cnt == 1'b1)
Uart_clk <= 1'b1;
else
Uart_clk <= 1'b0;
//下面就是在进行数据传输的计数,即在有数据传输的时候就会进行计数
always @(posedge clk or negedge rst_n)
if(!rst_n)
Uart_bps_cnt <= 4'd0;
else if(Uart_bps_cnt == 4'd11)
Uart_bps_cnt <= 4'd0;
else if(Uart_clk)
Uart_bps_cnt <= Uart_bps_cnt + 1'b1;
else
Uart_bps_cnt <= Uart_bps_cnt;
//下面通过计数,就可以选定该传什么值了
always @(posedge clk or negedge rst_n)
if(!rst_n)
Tx_data <= 1'b1;
else begin
case(Uart_bps_cnt)
0:Tx_data <= 1'b1;
1:Tx_data <= Start_bit;
2:Tx_data <= data_byte[0];
3:Tx_data <= data_byte[1];
4:Tx_data <= data_byte[2];
5:Tx_data <= data_byte[3];
6:Tx_data <= data_byte[4];
7:Tx_data <= data_byte[5];
8:Tx_data <= data_byte[6];
9:Tx_data <= data_byte[7];
10:Tx_data <= Stop_bit;
default:Tx_data <= 1'b1;
endcase
end
always @(posedge clk or negedge rst_n)
if(!rst_n)
Tx_done <= 1'b0;
else if(Uart_bps_cnt == 4'd11)
Tx_done <= 1'b1;
else
Tx_done <= 1'b0;
always @(posedge clk or negedge rst_n)
if(!rst_n)
Uart_State <= 1'b0;
else if(Start_en)
Uart_State <= 1'b1;
else if(Uart_bps_cnt == 4'd11)
Uart_State <= 1'b0;
else
Uart_State <= Uart_State;
整个数据数据的传输(TX)主要可分为以下几个步骤实现:、
1.产生双方约定的波特率时钟的计数值(首先要计算好例如;时钟是50MHz 需要的时钟是9.6KHz 这些即计数:50000/9.6 = 5208 )
2.有了波特率计数值后就是产生这个计数值的计数器(但是一定要注意计数的条件是在数据传输的过程中进行)
3.有了计数就可以在计数的过程中,等于某个值的时候来表示生产波特率脉冲时钟(但是一定要在下一轮计数也是这个值)
3.有了计数脉冲,就可以根据这个脉冲进行计数,因为一共就传10个数(本例中:起始位(1个) + 数据位(8个)+停止位(1个))但是计数要计到11因为初始状态是要的
4.有了脉冲计数就可以根据计数值进行选择,传什么数出去了。
5.当计数值到11后就可以关掉计数的波特率计数器等等一些辅助操作了。