zoukankan      html  css  js  c++  java
  • FPGA学习-9:时序电路之串口通讯模块

    通信是时序电路的基础之一

    要保证信息能够在不同模块直接准确传输

    通信协议是保证信息传输的格式要求

    那么下面我们就来设计个最简单的

    也是最基础的串口通信模块

    串口通信时序这里不做介绍


    该串口模块的功能描述如下:

    波特率9600

    停止位1

    校验位无

    接收字节后将字节加一发送回去


    首先是PLL模块

    PLL模块给串口模块提供稳定的时钟信号

    代码如下:

    module PLL(
    	input[31:0] sub,
    	input clk,	
    	input rst,
    	output reg clk_out
    );	
    reg[31:0] cnt;
    
    initial begin
    	cnt = 32'd1;
    	clk_out = 0;
    end	
    
    always @(posedge clk or negedge rst) begin
    	if (rst == 0) begin
    		cnt = 32'd1;	
    		clk_out = 0;
    	end			
    	else if(cnt < sub) begin	
    		cnt = cnt + 1;
    	end			
    	else if(cnt >= sub) begin	
    		clk_out = ~clk_out;	
    		cnt = 32'd1;
    	end
    end
    endmodule
    

    然后是串口模块

    代码如下

    module USART(
    	input clk,	//24Mhz
    	input rst,
    	input rx,
    	output reg tx
    );	
    
    reg[7:0] buff;
    reg[7:0] rx_shift;
    reg[7:0] tx_shift;
    
    initial begin
    	tx = 1;
    	buff = 0;	
    	rx_shift = 0;	
    	tx_shift = 0;
    end	
    
    wire clk0;
    PLL pll(
    .sub (32'd1250),
    .clk (clk),
    .rst (rst),
    .clk_out (clk0)
    );
    
    integer rx_i = 0;
    integer tx_i = 0;
    integer rx_flag = 0;
    integer tx_flag = 0;
    integer send_flag = 0;
    
    always @(posedge clk0 or negedge rst)begin
    	if(rst == 0)begin
    		rx_i=0;	
    		tx_i = 0;
    		rx_flag=0;		
    		tx_flag = 0;		
    		tx = 1;
    		buff = 0;	
    		rx_shift = 0;		
    		tx_shift = 0;
    	end		
    	else begin
    		case(rx_flag)
    			0:begin	//起始位
    				if(rx==0)begin				
    					rx_flag=1;
    				end
    			end
    			1:begin//数据位			
    				rx_shift = rx_shift + {rx,7'd0};
    				if(rx_i < 7)begin				
    					rx_shift = rx_shift >> 1;	
    				end	
    				rx_i = rx_i + 1;			
    				if (rx_i >= 8)begin				
    					rx_flag = 2;					
    					rx_i = 0;
    				end	
    			end	
    			2:begin//结束位		
    				if(rx == 1)begin		
    					buff = rx_shift;				
    					rx_shift = 0;			
    					send_flag = 1;			
    					rx_flag = 0;
    				end	
    			end	
    		endcase		
    		
    		if( send_flag==1 )begin
    			case(tx_flag)	
    				0:begin		
    					tx_shift = buff + 1;
    					tx = 0;			
    					tx_flag=1;
    				end
    				1:begin					
    					tx = tx_shift[0];	
    					tx_shift = tx_shift >> 1;				
    					tx_i = tx_i+1;				
    					if(tx_i >= 8)begin					
    						tx_flag = 2;					
    						tx_i = 0;
    					end		
    				end			
    				2:begin						
    					tx = 1;			
    					tx_flag = 0;	
    					send_flag = 0;
    				end
    			endcase
    		end				
    	end	
    end
    
    endmodule
    

    管脚映射如下:

    0

    连接USB转串口模块

    使用串口调试软件进行测试:

    实际使用效果如下;

    1

    可以看到,我们发送一串十六进制数据

    它会自动将数据加一后再返回来

    可以证明我们的代码没有问题

  • 相关阅读:
    突破ASLR之理论篇
    安装cocoaPods
    iOS 文字渐变
    iOS_科大讯飞快速实现语音搜索功能Demo
    Button宽度自定义
    全局手势按钮(随意拖动,点击事件)
    文字广告轮播这个就够用了
    一些有趣的三方开源库
    SVN的简单使用和积累
    如何在手机上面安装iPA应用包
  • 原文地址:https://www.cnblogs.com/prprpr/p/14878147.html
Copyright © 2011-2022 走看看