2759 views|1 replies

2870

Posts

4

Resources
The OP
 

SparkRoad Review (7) - FPGA Serial Port Test [Copy link]

 

Anlu's development board is equipped with a USB2UART module, which is connected to the USB-to-serial port through the microcontroller on the board. It is not possible to open the built-in routine 6_uart_loopback and run it by itself. Because the default pin is not connected to the UART2USB line, the pin must be set to the pin specified by USB2UART.

1. Open the project uart.al, file mini_EG4S20BG256.adc

2. Modify the specified resources of the file. 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. After synthesizing the project, burn it into the board and you can experiment.

This is an explanation of the project files in the experiment. The speed_setting.v file is used to modify the baud rate. There are two files corresponding to the two settings of sending and receiving.

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

Just modify parameter BPS_SET = 96, //96 in the baud rate, the actual parameter line is: `define BPS_PARA (10_000_000/CLK_PERIORD/BPS_SET) //10_000_000/`CLK_PERIORD/96;

Don't touch anything else. In fact, the main thing is a "divider"

Next, let's analyze the serial port sending file, 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

This file is a bit confusing, mainly because there is an extra step in it, which is the process of transferring the received data to tx_data. This process should not be written into this module. My suggestion is to write it into the state machine in the top-level file.

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

Next comes the main part of the output.

//---------------------------------------------------------
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;

This program uses a counter instead of a standard state machine. This depends on personal preference. The advantage of a counter is that it takes up less resources, but it is not very flexible and has poor configurability. The disadvantage of a state machine is that it has a complex structure. This is up to your preference. This test ends here. I hope you can correct me.

This post is from Domestic Chip Exchange

Latest reply

The process of transferring the received data to tx_data is written to the state machine in the top-level file. It is a good suggestion and is collected.   Details Published on 2022-5-9 08:08
 
 

6593

Posts

0

Resources
2
 

The process of transferring the received data to tx_data is written to the state machine in the top-level file. It is a good suggestion and is collected.

This post is from Domestic Chip Exchange
 
 
 

Guess Your Favourite
Just looking around
Find a datasheet?

EEWorld Datasheet Technical Support

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号
快速回复 返回顶部 Return list