1824 views|1 replies

81

Posts

0

Resources
The OP
 

SparkRoad Serial Communication [Copy link]

 

Serial communication is a commonly used low-speed communication interface. It is also used more frequently during debugging. First, implement the serial port.

UART serial communication requires two signal lines, one for serial transmission and the other for serial reception. A frame of data in the UART transmission or reception process consists of four parts: start bit, data bit, parity bit and stop bit.

The protocol is as follows:

Because the serial port is asynchronous, the receiving and sending are implemented separately. The following is the receiving end:

`timescale 1ns / 1ns

module uartrx(
input    clk,
input    rst_n,
//uart interface
input    uart_rx,
//user interface
output          dataout_vld ,
output   [7:0]  dataout
);

//localparam  
localparam  BPS  =  9600 ;
localparam  BPS_CNT  =  2500 ;  //  T/BPS

//reg define
reg   [12:0]   pcnt ;
reg   [2:0]    rx_dly ;
reg   [3:0]    rx_cnt ;
reg   [7:0]    rx_reg ;
reg            rx_en  ;

//wire  define
wire     rx_falling  ;

assign   rx_falling  =  rx_dly[2] & ~rx_dly[1] ;

//打拍 同步
always @(posedge clk or negedge rst_n)
begin
   if(rst_n == 1'b0)
      rx_dly  <=  3'b000 ;
   else
      rx_dly  <=  {rx_dly[1:0], uart_rx} ;
end

//接收到起始信号,开始标志
always @(posedge clk or negedge rst_n)
begin
   if(rst_n == 1'b0)
     rx_en  <= 1'b0 ;
   else if(rx_falling == 1'b1)
     rx_en  <= 1'b1 ;
   else if(rx_cnt == 4'd9)
     rx_en  <= 1'b0 ;
   else ;
end

//rx 接收字节计数
always @(posedge clk or negedge rst_n)
begin
   if(rst_n == 1'b0)
     rx_cnt  <=  4'd0;
   else if(rx_en == 1'b1)
     if(pcnt == BPS_CNT -1'b1)
         rx_cnt  <=  rx_cnt + 1'b1;
     else;
   else 
     rx_cnt  <=  4'd0;
end

//PBS CNT
always @(posedge clk or negedge rst_n)
begin
   if(rst_n == 1'b0)
     pcnt  <=  13'd0;
   else if(rx_en == 1'b1)
     if(pcnt == BPS_CNT -1'b1)
         pcnt  <= 13'd0 ;
     else
         pcnt  <= pcnt + 1'b1 ;
   else 
     pcnt  <=  13'd0;
end

//rx 接收数据
always @(posedge clk or negedge rst_n)
begin
   if(rst_n == 1'b0)
     rx_reg  <=  8'b0;
   else if(pcnt == BPS_CNT/2 -1'b1)
     case(rx_cnt)
       4'd1: rx_reg[0]  <= uart_rx ;
       4'd2: rx_reg[1]  <= uart_rx ;
       4'd3: rx_reg[2]  <= uart_rx ;
       4'd4: rx_reg[3]  <= uart_rx ;
       4'd5: rx_reg[4]  <= uart_rx ;
       4'd6: rx_reg[5]  <= uart_rx ;
       4'd7: rx_reg[6]  <= uart_rx ;
       4'd8: rx_reg[7]  <= uart_rx ;
     default : ;
     endcase
   else ;	   
end

assign  dataout_vld  =  (rx_cnt == 4'd9) ? 1'b1 : 1'b0;
assign  dataout      =  rx_reg ;


endmodule

The sending end and the receiving end are similar, that is, one sends data and the other receives data.

`timescale 1ns / 1ns

module uarttx(
input    clk,
input    rst_n,
//uart interface
output   uart_tx,
//user interface
input           datain_vld,
input    [7:0]  datain,
output          uart_ack
);

//localparam  
localparam  BPS  =  9600 ;
localparam  BPS_CNT  =  2500 ;  //  T/BPS

//reg define
reg   [12:0]   pcnt ;
reg   [2:0]    tx_dly ;
reg   [3:0]    tx_cnt ;
reg   [7:0]    tx_reg ;
reg            tx_en  ;
reg            uart_tx ;

//wire  define
wire     tx_rising  ;

assign   tx_rising  =  ~tx_dly[2] & tx_dly[1] ;

//打拍 同步
always @(posedge clk or negedge rst_n)
begin
   if(rst_n == 1'b0)
      tx_dly  <=  3'b000 ;
   else
      tx_dly  <=  {tx_dly[1:0], datain_vld} ;
end

//接收到起始信号,开始标志
always @(posedge clk or negedge rst_n)
begin
   if(rst_n == 1'b0)
     tx_en  <= 1'b0 ;
   else if(tx_rising == 1'b1)
     tx_en  <= 1'b1 ;
   else if(tx_cnt == 4'd9)
     tx_en  <= 1'b0 ;
   else ;
end

//rx 接收字节计数
always @(posedge clk or negedge rst_n)
begin
   if(rst_n == 1'b0)
     tx_cnt  <=  4'd0;
   else if(tx_en == 1'b1)
     if(pcnt == BPS_CNT -1'b1)
         tx_cnt  <=  tx_cnt + 1'b1;
     else;
   else 
     tx_cnt  <=  4'd0;
end

//PBS CNT
always @(posedge clk or negedge rst_n)
begin
   if(rst_n == 1'b0)
     pcnt  <=  13'd0;
   else if(tx_en == 1'b1)
     if(pcnt == BPS_CNT -1'b1)
         pcnt  <= 13'd0 ;
     else
         pcnt  <= pcnt + 1'b1 ;
   else 
     pcnt  <=  13'd0;
end

always @(posedge clk or negedge rst_n)
begin
   if(rst_n == 1'b0)
     tx_reg  <=  8'b0;
   else if(tx_en == 1'b1)
//     tx_reg  <=  8'h55;
     tx_reg  <=  datain;     
   else ;	   
end

//tx 接收数据
always @(posedge clk or negedge rst_n)
begin
   if(rst_n == 1'b0)
     uart_tx  <=  1'b1;
   else if(tx_en == 1'b1)
     case(tx_cnt)
       4'd0: uart_tx  <= 1'b0      ;   
       4'd1: uart_tx  <= tx_reg[0] ;
       4'd2: uart_tx  <= tx_reg[1] ;
       4'd3: uart_tx  <= tx_reg[2] ;
       4'd4: uart_tx  <= tx_reg[3] ;
       4'd5: uart_tx  <= tx_reg[4] ;
       4'd6: uart_tx  <= tx_reg[5] ;
       4'd7: uart_tx  <= tx_reg[6] ;
       4'd8: uart_tx  <= tx_reg[7] ;
       4'd9: uart_tx  <= 1'b1      ;
     default : ;
     endcase
   else ;	   
end

assign  uart_ack  =  (tx_en == 1'b1) ? 1'b0 : 1'b1;
assign  dataout      =  tx_reg ;


endmodule

In fact, it is better to use one module to represent the baud rate between TX and RX, so that it is convenient to modify the baud rate of different rates later and realize adjustable baud rate.

Then implement the top file, associate tx, rx, and implement receiving and sending. Because nothing else has been implemented, the byte is sent directly after receiving the data.

wire    [7:0]  datain  ;
wire           datain_vld;
wire    [7:0]  dataout     ;
wire           dataout_vld ;
assign  datain     =  dataout ;
assign  datain_vld =  dataout_vld ;


uarttx u_uart_tx(
.clk              ( CLK_24M    ),
.rst_n            ( rst_n      ),
.uart_tx          ( UART_TX    ),
.datain_vld       ( datain_vld ),
.datain           ( datain     ),
.uart_ack         ( uart_ack   )
);

uartrx u_uart_rx(
.clk              ( CLK_24M    ),
.rst_n            ( rst_n      ),
.uart_rx          ( UART_RX    ),
.dataout_vld      ( dataout_vld),
.dataout          ( dataout    )
);

If you don't simulate the board, it's just a rogue. Then use the modelsim function to simulate and check whether the basic sending and receiving functions are normal.

Simply check that the data bits sent and received meet the requirements, and then test the performance directly on the board.

Use the serial communication tool to connect to the virtual interface, and keep sending data "Anlogic fpga" to check whether the data received by the serial tool is normal.

Through verification, the basic functions of the serial communication tool are normal.

The UART to localbus protocol will be added later to implement the control of each chip on the board by issuing instructions through the serial port, which will also facilitate later debugging.

This post is from Domestic Chip Exchange

Latest reply

The basic function test of the serial communication tool is generally normal if the connection is normal and the settings are correct. Next, I look forward to other tests by the host.   Details Published on 2022-5-6 07:53
 
 

6555

Posts

0

Resources
2
 

The basic function test of the serial communication tool is generally normal if the connection is normal and the settings are correct. Next, I look forward to other tests by the host.

This post is from Domestic Chip Exchange
 
 
 

Guess Your Favourite
Just looking around
Find a datasheet?

EEWorld Datasheet Technical Support

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

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