2749|1

2870

帖子

4

TA的资源

五彩晶圆(中级)

楼主
 

SparkRoad测评(7)-FPGA串口测试 [复制链接]

 

安路的开发板上是带有USB2UART模块的,这个模块是通过板子上的单片机与USB转串口相连接的,打开自带的例程6_uart_loopback自接运行是不可以的。因为默认的引脚是不接在UART2USB的线上的,所以必须将引脚设定到USB2UART指定的引脚上。

1、打开项目uart.al,文件mini_EG4S20BG256.adc

  2、修改文件的指定资源。uart_tx E16、uart_rx F16

set_pin_assignment {ext_clk_25m}    { LOCATION = K14;  }
set_pin_assignment {ext_rst_n}  { LOCATION = L12;  }     ##KEY_C

##set_pin_assignment {uart_tx} { LOCATION = C11; }         
##set_pin_assignment {uart_rx} { LOCATION = B15; }

set_pin_assignment {uart_tx} { LOCATION = E16; }      
set_pin_assignment {uart_rx} { LOCATION = F16; }

3、将项目综合后,烧入板子就可以实验了。

 这个说明一下实验中的项目文件,speed_setting.v这个文件是用来修改波特率的。这里有两个文件对应的是收发两个设置

module speed_setting
#(
    parameter BPS_SET      =   96,  //波特率
    parameter CLK_PERIORD  =   40   //时钟周期40ns(25MHz)
)
(
	input	clk,		//25MHz主时钟
	input	rst_n,		//低电平复位信号
	input	bps_start,	//接收到数据后,波特率时钟启动信号置位
	output	clk_bps		//clk_bps的高电平为接收或者发送数据位的中间采样点
);

`define BPS_PARA	(10_000_000/CLK_PERIORD/BPS_SET)	//10_000_000/`CLK_PERIORD/96;
`define BPS_PARA_2	(`BPS_PARA/2)						//BPS_PARA/2;	

reg	[12:0] cnt;		    //分频计数
reg clk_bps_r;	        //波特率时钟寄存器
reg	[2:0] uart_ctrl;	//uart波特率选择寄存器

always@(posedge clk or negedge rst_n)
begin
    if(!rst_n)
        cnt <= 13'd0;
	else if((cnt == `BPS_PARA) || !bps_start)
        cnt <= 13'd0;	    //波特率计数清零
	else
        cnt <= cnt + 1'b1;  //波特率时钟计数启动
end

always@(posedge clk or negedge rst_n)
begin
	if(!rst_n)
        clk_bps_r <= 1'b0;
	else if(cnt == `BPS_PARA_2)
        clk_bps_r <= 1'b1;			//clk_bps_r高电平为接收数据位的中间采样点,同时也作为发送数据的数据改变点
	else
        clk_bps_r <= 1'b0;
end

assign clk_bps = clk_bps_r;

endmodule

只要修改parameter BPS_SET = 96, //波特率 其中的96就可以了,其实的参数行是:`define BPS_PARA (10_000_000/CLK_PERIORD/BPS_SET) //10_000_000/`CLK_PERIORD/96;

别的就不要动了。其实主要的就是一个“分频器”

下面我们来分析一下串口的发送文件,my_uart_tx.v

module my_uart_tx
(
	input			clk,
	input			rst_n,
	input	[7:0]	rx_data,
	input			rx_int,
	output			uart_tx,
	input			clk_bps,
	output			bps_start
);

//---------------------------------------------------------
reg 	rx_int0,rx_int1,rx_int2;	//rx_int信号寄存器
wire 	neg_rx_int;					//rx_int下降沿标志位

always @ (posedge clk or negedge rst_n)
begin 
	if(!rst_n) 
    begin
		rx_int0 <= 1'b0;
		rx_int1 <= 1'b0;
		rx_int2 <= 1'b0;
	end
	else 
    begin
		rx_int0 <= rx_int;
		rx_int1 <= rx_int0;
		rx_int2 <= rx_int1;
	end
end

assign neg_rx_int =  ~rx_int1 & rx_int2;	//捕捉到下降沿后,neg_rx_int拉高保持一个主时钟周期

//---------------------------------------------------------
reg	[7:0] 	tx_data;		//待发送数据的寄存器
reg 		bps_start_r;
reg 		tx_en;			//发送数据使能信号,高有效
reg	[3:0] 	num;

always @ (posedge clk or negedge rst_n)
begin 
	if(!rst_n) 
    begin
		bps_start_r <= 1'bz;
		tx_en 		<= 1'b0;
		tx_data 	<= 8'd0;
	end
	else if(neg_rx_int) 
    begin		                    //接收数据完毕,准备把接收到的数据发回去
		bps_start_r <= 1'b1;
		tx_data 	<= rx_data;		//把接收到的数据存入发送数据寄存器
		tx_en 		<= 1'b1;		//进入发送数据状态中
	end
	else if(num == 4'd10) 
    begin		                    //数据发送完成,复位
		bps_start_r <= 1'b0;
		tx_en		<= 1'b0;
	end
end

assign bps_start = bps_start_r;

//---------------------------------------------------------
reg uart_tx_r;

always @ (posedge clk or negedge rst_n)
begin
	if(!rst_n) 
    begin
		num 		<= 4'd0;
		uart_tx_r 	<= 1'b1;
	end
	else if(tx_en) 
    begin
		if(clk_bps)	
        begin
			num <= num+1'b1;
			case (num)
				4'd0: uart_tx_r <= 1'b0; 		//发送起始位
				4'd1: uart_tx_r <= tx_data[0];	//发送bit0
				4'd2: uart_tx_r <= tx_data[1];	//发送bit1
				4'd3: uart_tx_r <= tx_data[2];	//发送bit2
				4'd4: uart_tx_r <= tx_data[3];	//发送bit3
				4'd5: uart_tx_r <= tx_data[4];	//发送bit4
				4'd6: uart_tx_r <= tx_data[5];	//发送bit5
				4'd7: uart_tx_r <= tx_data[6];	//发送bit6
				4'd8: uart_tx_r <= tx_data[7];	//发送bit7
				4'd9: uart_tx_r <= 1'b1;		//发送结束位
			 	default: uart_tx_r <= 1'b1;
			endcase
		end
		else if(num == 4'd10)
                num <= 4'd0;		
	end
end

assign uart_tx = uart_tx_r;

endmodule

这个文件让人看了有点疑惑,主要是这里面多了一步,将收到的数据转出到tx_data的过程,这个过程真不应该写到这个模块中,我的建议是写到顶层的文件中的状态机当中。

always @ (posedge clk or negedge rst_n)
begin 
	if(!rst_n) 
    begin
		bps_start_r <= 1'bz;
		tx_en 		<= 1'b0;
		tx_data 	<= 8'd0;
	end
	else if(neg_rx_int) 
    begin		                    //接收数据完毕,准备把接收到的数据发回去
		bps_start_r <= 1'b1;
		tx_data 	<= rx_data;		//把接收到的数据存入发送数据寄存器
		tx_en 		<= 1'b1;		//进入发送数据状态中
	end
	else if(num == 4'd10) 
    begin		                    //数据发送完成,复位
		bps_start_r <= 1'b0;
		tx_en		<= 1'b0;
	end
end

接下来是输出的主要部分。

//---------------------------------------------------------
reg uart_tx_r;

always @ (posedge clk or negedge rst_n)
begin
	if(!rst_n) 
    begin
		num 		<= 4'd0;
		uart_tx_r 	<= 1'b1;
	end
	else if(tx_en) 
    begin
		if(clk_bps)	
        begin
			num <= num+1'b1;
			case (num)
				4'd0: uart_tx_r <= 1'b0; 		//发送起始位
				4'd1: uart_tx_r <= tx_data[0];	//发送bit0
				4'd2: uart_tx_r <= tx_data[1];	//发送bit1
				4'd3: uart_tx_r <= tx_data[2];	//发送bit2
				4'd4: uart_tx_r <= tx_data[3];	//发送bit3
				4'd5: uart_tx_r <= tx_data[4];	//发送bit4
				4'd6: uart_tx_r <= tx_data[5];	//发送bit5
				4'd7: uart_tx_r <= tx_data[6];	//发送bit6
				4'd8: uart_tx_r <= tx_data[7];	//发送bit7
				4'd9: uart_tx_r <= 1'b1;		//发送结束位
			 	default: uart_tx_r <= 1'b1;
			endcase
		end
		else if(num == 4'd10)
                num <= 4'd0;		
	end
end

assign uart_tx = uart_tx_r;

这个程序使用了一个计数器,而不是一个标准状态机,这点根据个人的喜好了,计数器的优点是资源占用少,但是可配置性差,不是很灵活,状态机的缺点是结构复杂。这就是看各自的喜好了。本次测试到此为止,希望大家多多指正。

最新回复

将收到的数据转出到tx_data的过程,写到顶层的文件中的状态机当中建议很好,收藏   详情 回复 发表于 2022-5-9 08:08
点赞 关注
 
 

回复
举报

6587

帖子

0

TA的资源

五彩晶圆(高级)

沙发
 

将收到的数据转出到tx_data的过程,写到顶层的文件中的状态机当中建议很好,收藏

 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/10 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表