FPGA sample - 如何使用 UART loopback 驗證
在範例中,使用 Intel MAX 10 core board 上的 CP1202 , 把系統的 USB 資料轉成 UART 的資料, 再由 FPGA 的 RX 接收, 再由 TX 傳送給系統的 USB.
硬體方塊圖
在硬體方面,只需要把 intel MAX 10 core board 的 mini USB 連接到 Notebook 就完成了. 因為在 intel MAX 10 core board 內有 CP2102 是一個 USB COM 的晶片, 所以當 intel MAX 10 core board 連接到 notebook, 就會建立一個 COM.
Notebook 就可以透過 COM 和 intel MAX 10 core board 溝通.
FPGA 程式碼方塊圖
Notebook 由 Termite 應用程式輸入資料,經過 USB COM(CP2102) 傳送到 FPGA Rx 程式模組, 經過 40ns (2 clock) 除雜訊功能,開始接收資料, start 由高阻抗變成高電位, int 也同樣變成高電位.啟動 Rx Config 採樣模組,在採樣點(資料位元的中心點), bps 就會變成高電位, Rx 模組讀取資料放到 Rx data 陣列. 直到資料接收完整, start 變成低電位, int 也同時變成低電位.
當 int 變成高電位,Tx 模組經過 20ns (1 clock) 除雜訊功能,開始計數接收資料,直到資料接收完整,啟動 Tx Config 傳送定位模組, 在資料定位點(資料位元的結束點), bps 會變成高電位,Tx 模組傳送資料到 notebook.
範例程式位於 Github 的 FPGA-Bus-Uart-Loopback-sample
硬體方塊圖
在硬體方面,只需要把 intel MAX 10 core board 的 mini USB 連接到 Notebook 就完成了. 因為在 intel MAX 10 core board 內有 CP2102 是一個 USB COM 的晶片, 所以當 intel MAX 10 core board 連接到 notebook, 就會建立一個 COM.
Notebook 就可以透過 COM 和 intel MAX 10 core board 溝通.
FPGA 程式碼方塊圖
Notebook 由 Termite 應用程式輸入資料,經過 USB COM(CP2102) 傳送到 FPGA Rx 程式模組, 經過 40ns (2 clock) 除雜訊功能,開始接收資料, start 由高阻抗變成高電位, int 也同樣變成高電位.啟動 Rx Config 採樣模組,在採樣點(資料位元的中心點), bps 就會變成高電位, Rx 模組讀取資料放到 Rx data 陣列. 直到資料接收完整, start 變成低電位, int 也同時變成低電位.
當 int 變成高電位,Tx 模組經過 20ns (1 clock) 除雜訊功能,開始計數接收資料,直到資料接收完整,啟動 Tx Config 傳送定位模組, 在資料定位點(資料位元的結束點), bps 會變成高電位,Tx 模組傳送資料到 notebook.
Rx/Tx Config 採樣模組
`define BPS_115200
`define CLK_PERIORD 20 // define periord is 20ns(50MHz)
`define BPS_SET 1152 // define baudrate is 115200bps
`define BPS_PARA (10_000_000/`CLK_PERIORD/`BPS_SET)
// bit width count = 1/115200/20(ns)
// = 1000_000_000/115200/20(sec)
// = 10_000_000/CLK_PERIORD/BPS_SET;
`define BPS_PARA_2 (`BPS_PARA/2)
// BPS_PARA/2;
// sample frequency is 2 * baud-rate
//-----------------------------------------------------------
// function : bit width counter
// input : ext_clk (clock) 50MHz
// : ext_rst_n (reset)
// output : cnt
//-----------------------------------------------------------
reg[12:0] cnt; // sample counter
reg[2:0] uart_ctrl; // uart baud-rate select register
always @ (posedge clk or negedge rst_n)
if(!rst_n) cnt <= 13'd0;
else if((cnt == `BPS_PARA) || !bps_start)
cnt <= 13'd0; // clear sample counter
else cnt <= cnt+1'b1; // counting sample
//-----------------------------------------------------------
// function : bit sample counter (middle of bit)
// input : ext_clk (clock) 50MHz
// : ext_rst_n (reset)
// output : clk_bps_r
//-----------------------------------------------------------
reg clk_bps_r; // baud-rate register
always @ (posedge clk or negedge rst_n)
if(!rst_n) clk_bps_r <= 1'b0;
else if(cnt == `BPS_PARA_2)
clk_bps_r <= 1'b1; // sample on middle of clock
else clk_bps_r <= 1'b0;
assign clk_bps = clk_bps_r;
Rx 的模組
//-----------------------------------------------------------
// function : bit debounce
// input : ext_clk (clock) 50MHz
// : ext_rst_n (reset)
// output : neg_uart_rx
//-----------------------------------------------------------
reg uart_rx0,uart_rx1,uart_rx2,uart_rx3; // regiter for receiver
wire neg_uart_rx; // sample data at falling edge
always @ (posedge clk or negedge rst_n)
if(!rst_n) begin
uart_rx0 <= 1'b0;
uart_rx1 <= 1'b0;
uart_rx2 <= 1'b0;
uart_rx3 <= 1'b0;
end
else begin
uart_rx0 <= uart_rx;
uart_rx1 <= uart_rx0;
uart_rx2 <= uart_rx1;
uart_rx3 <= uart_rx2;
end
// falling edge to debounce 40ns-80ns noise
// neg_uart_rx active when data receiving
assign neg_uart_rx = uart_rx3 & uart_rx2 & ~uart_rx1 & ~uart_rx0;
//-----------------------------------------------------------
// function : bit debounce
// input : ext_clk (clock) 50MHz
// : ext_rst_n (reset)
// output : neg_uart_rx
//-----------------------------------------------------------
reg bps_start_r; // bit start receive
reg[3:0] num; // bit shift times
always @ (posedge clk or negedge rst_n)
if(!rst_n) begin
bps_start_r <= 1'bz;
rx_int <= 1'b0;
end
else if(neg_uart_rx) begin // receive falling edge trigger
bps_start_r <= 1'b1; // start receiver
rx_int <= 1'b1; // enable receiver interrput
end
else if(num == 4'd9) begin // receiver complete
bps_start_r <= 1'b0; // clear start flag
rx_int <= 1'b0; // disable receiver interrupt
end
assign bps_start = bps_start_r;
//-----------------------------------------------------------
// function : receive UART data and store to
// input : ext_clk (clock) 50MHz
// : ext_rst_n (reset)
// output : rx_data_r
//-----------------------------------------------------------
reg[7:0] rx_data_r; // receiver buffer unteil next receive
reg[7:0] rx_temp_data; // receiver data buffer
always @ (posedge clk or negedge rst_n)
if(!rst_n) begin
rx_temp_data <= 8'd0;
num <= 4'd0;
rx_data_r <= 8'd0;
end
else if(rx_int) begin // receivr handle
if(clk_bps) begin // read data and store
// receive 1 start bit, 8 data bits and 1-2 stop bits
num <= num+1'b1;
case (num)
4'd1: rx_temp_data[0] <= uart_rx; // store bit 0
4'd2: rx_temp_data[1] <= uart_rx; // store bit 1
4'd3: rx_temp_data[2] <= uart_rx; // store bit 2
4'd4: rx_temp_data[3] <= uart_rx; // store bit 3
4'd5: rx_temp_data[4] <= uart_rx; // store bit 4
4'd6: rx_temp_data[5] <= uart_rx; // store bit 5
4'd7: rx_temp_data[6] <= uart_rx; // store bit 6
4'd8: rx_temp_data[7] <= uart_rx; // store bit 7
default: ;
endcase
end
else if(num == 4'd9) begin // check data valid
num <= 4'd0; // clear data counter
rx_data_r <= rx_temp_data; // store to rx_data
end
end
assign rx_data = rx_data_r;
Tx 的模組
//-----------------------------------------------------------
// function : bit debounce
// input : ext_clk (clock) 50MHz
// : ext_rst_n (reset)
// output : neg_rx_int
//-----------------------------------------------------------
reg rx_int0,rx_int1,rx_int2; // rx_int fall edge register
wire neg_rx_int; // rx_int fall edge trigger
always @ (posedge clk or negedge rst_n)
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
// capture falling edge, neg_rx_int hold 1 clock
assign neg_rx_int = ~rx_int1 & rx_int2;
//-----------------------------------------------------------
// function : Enable and start data transmit
// input : ext_clk (clock) 50MHz
// : ext_rst_n (reset)
// output : bps_start_t
//-----------------------------------------------------------
reg[7:0] tx_data; // Transmit data buffer
reg bps_start_t; // Start Transmit data
reg tx_en; // Transmit enable
reg[3:0] num; // Transmit bit count
always @ (posedge clk or negedge rst_n)
if(!rst_n) begin
bps_start_t <= 1'bz;
tx_en <= 1'b0;
tx_data <= 8'd0;
end
else if(neg_rx_int) begin // receive complete and ready to trnsmit
bps_start_t <= 1'b1; // start transmit
tx_data <= rx_data; // store receive data to
tx_en <= 1'b1; // enable data transmit
end
else if(num == 4'd10) begin // transmit complete
bps_start_t <= 1'b0; // stop transmit
tx_en <= 1'b0; // disable data transmit
end
assign bps_start = bps_start_t;
//-----------------------------------------------------------
// function : bit debounce
// input : ext_clk (clock) 50MHz
// : ext_rst_n (reset)
// output : neg_uart_rx
//-----------------------------------------------------------
reg uart_tx_t;
always @ (posedge clk or negedge rst_n)
if(!rst_n) begin
num <= 4'd0;
uart_tx_t <= 1'b1;
end
else if(tx_en) begin
if(clk_bps) begin
num <= num+1'b1;
case (num)
4'd0: uart_tx_t <= 1'b0; // start transmot
4'd1: uart_tx_t <= tx_data[0]; // send bit 0
4'd2: uart_tx_t <= tx_data[1]; // send bit 1
4'd3: uart_tx_t <= tx_data[2]; // send bit 2
4'd4: uart_tx_t <= tx_data[3]; // send bit 3
4'd5: uart_tx_t <= tx_data[4]; // send bit 4
4'd6: uart_tx_t <= tx_data[5]; // send bit 5
4'd7: uart_tx_t <= tx_data[6]; // send bit 6
4'd8: uart_tx_t <= tx_data[7]; // send bit 7
4'd9: uart_tx_t <= 1'b1; // end transmit
default: uart_tx_t <= 1'b1;
endcase
end
else if(num == 4'd10) num <= 4'd0; // reset
end
assign uart_tx = uart_tx_t;
範例程式位於 Github 的 FPGA-Bus-Uart-Loopback-sample




留言
張貼留言