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
留言
張貼留言