quartus Ⅱ 12.1 使用教程(4) uart 測試

開發板使用的是EP4CE15F23C8,軟件使用的是quartus  12.1 ,工程實現的功能是使用uart進行迴環測試

頂層

module uart_test(
    i_clk,
    i_rst_n,
    rx,
    tx
    
    );
    
input   i_clk;
input   i_rst_n;
input   rx;
output  tx;



wire    clk_out;
wire    wrsig;
wire    idle;
wire    tx;
wire    rx;
wire    [7:0] data_in;
wire    [7:0] data_out;
wire    rdsig;
wire    data_error;
wire    frame_error;

clk_div u1(
    .clk50(i_clk), 
    .rst_n(i_rst_n), 
    .clkout(clk_out)
    );
       
uart_tx u2(
    .clk(clk_out), 
    .rst_n(i_rst_n), 
    .datain(data_out), 
    .wrsig(rdsig), 
    .idle(idle), 
    .tx(tx)
    );
       
uart_rx u3(
    .clk(clk_out), 
    .rst_n(i_rst_n), 
    .rx(rx), 
    .dataout(data_out), 
    .rdsig(rdsig), 
    .dataerror(data_error), 
    .frameerror(frame_error)
    );      
    
endmodule

分頻模塊

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Module Name:    clkdiv 
//////////////////////////////////////////////////////////////////////////////////
module clk_div(clk50, rst_n, clkout);
input clk50;              //系統時鐘
input rst_n;              //收入復位信號
output clkout;            //採樣時鐘輸出
reg clkout;
reg [15:0] cnt;

/////分頻進程, 50Mhz的時鐘326分頻/////////
always @(posedge clk50 or negedge rst_n)   
begin
  if (!rst_n) begin
     clkout <=1'b0;
	  cnt<=0;
  end	  
  else if(cnt == 16'd162) begin
    clkout <= 1'b1;
    cnt <= cnt + 16'd1;
  end
  else if(cnt == 16'd325) begin
    clkout <= 1'b0;
    cnt <= 16'd0;
  end
  else begin
    cnt <= cnt + 16'd1;
  end
end
endmodule

發送模塊

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Module Name:    uarttx 
// 說明:16個clock發送一個bit, 一個起始位,8個數據位,一個校驗位,一個停止位
//////////////////////////////////////////////////////////////////////////////////
module uart_tx(clk, rst_n, datain, wrsig, idle, tx);
input clk;                //UART時鐘
input rst_n;              //系統復位
input [7:0] datain;       //需要發送的數據
input wrsig;              //發送命令,上升沿有效
output idle;              //線路狀態指示,高爲線路忙,低爲線路空閒
output tx;                //發送數據信號
reg idle, tx;
reg send;
reg wrsigbuf, wrsigrise;
reg presult;
reg[7:0] cnt;             //計數器
parameter paritymode = 1'b0;

////////////////////////////////////////////////////////////////
//檢測發送命令wrsig的上升沿
////////////////////////////////////////////////////////////////
always @(posedge clk)
begin
   wrsigbuf <= wrsig;
   wrsigrise <= (~wrsigbuf) & wrsig;  
end

////////////////////////////////////////////////////////////////
//啓動串口發送程序
////////////////////////////////////////////////////////////////
always @(posedge clk)
begin
  if (wrsigrise &&  (~idle))  //當發送命令有效且線路爲空閒時,啓動新的數據發送進程
  begin
     send <= 1'b1;
  end
  else if(cnt == 8'd168)      //一幀數據發送結束
  begin
     send <= 1'b0;
  end
end

////////////////////////////////////////////////////////////////
//串口發送程序, 16個時鐘發送一個bit
////////////////////////////////////////////////////////////////
always @(posedge clk or negedge rst_n)
begin
  if (!rst_n) begin
         tx <= 1'b0;
         idle <= 1'b0;
			cnt<=8'd0;
			presult<=1'b0;
  end		
  else if(send == 1'b1)  begin
    case(cnt)                 //產生起始位
    8'd0: begin
         tx <= 1'b0;
         idle <= 1'b1;
         cnt <= cnt + 8'd1;
    end
    8'd16: begin
         tx <= datain[0];    //發送數據0位
         presult <= datain[0]^paritymode;
         idle <= 1'b1;
         cnt <= cnt + 8'd1;
    end
    8'd32: begin
         tx <= datain[1];    //發送數據1位
         presult <= datain[1]^presult;
         idle <= 1'b1;
         cnt <= cnt + 8'd1;
    end
    8'd48: begin
         tx <= datain[2];    //發送數據2位
         presult <= datain[2]^presult;
         idle <= 1'b1;
         cnt <= cnt + 8'd1;
    end
    8'd64: begin
         tx <= datain[3];    //發送數據3位
         presult <= datain[3]^presult;
         idle <= 1'b1;
         cnt <= cnt + 8'd1;
    end
    8'd80: begin 
         tx <= datain[4];    //發送數據4位
         presult <= datain[4]^presult;
         idle <= 1'b1;
         cnt <= cnt + 8'd1;
    end
    8'd96: begin
         tx <= datain[5];    //發送數據5位
         presult <= datain[5]^presult;
         idle <= 1'b1;
         cnt <= cnt + 8'd1;
    end
    8'd112: begin
         tx <= datain[6];    //發送數據6位
         presult <= datain[6]^presult;
         idle <= 1'b1;
         cnt <= cnt + 8'd1;
    end
    8'd128: begin 
         tx <= datain[7];    //發送數據7位
         presult <= datain[7]^presult;
         idle <= 1'b1;
         cnt <= cnt + 8'd1;
    end
    8'd144: begin
         tx <= presult;      //發送奇偶校驗位
         presult <= datain[0]^paritymode;
         idle <= 1'b1;
         cnt <= cnt + 8'd1;
    end
    8'd160: begin
         tx <= 1'b1;         //發送停止位            
         idle <= 1'b1;
         cnt <= cnt + 8'd1;
    end
    8'd168: begin
         tx <= 1'b1;             
         idle <= 1'b0;       //一幀數據發送結束
         cnt <= cnt + 8'd1;
    end
    default: begin
         cnt <= cnt + 8'd1;
    end
   endcase
  end
  else  begin
    tx <= 1'b1;
    cnt <= 8'd0;
    idle <= 1'b0;
  end
end
endmodule

接收模塊

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Module name    uartrx.v
// 說明:          16個clock接收一個bit,16個時鐘採樣,取中間的採樣值
//////////////////////////////////////////////////////////////////////////////////
module uart_rx(clk, rst_n, rx, dataout, rdsig, dataerror, frameerror);
input clk;             //採樣時鐘
input rst_n;           //復位信號
input rx;              //UART數據輸入
output dataout;        //接收數據輸出
output rdsig;
output dataerror;      //數據出錯指示
output frameerror;     //幀出錯指示
reg[7:0] dataout;
reg rdsig, dataerror;
reg frameerror;
reg [7:0] cnt;
reg rxbuf, rxfall, receive;
parameter paritymode = 1'b0;
reg presult, idle;

always @(posedge clk)   //檢測線路的下降沿
begin
  rxbuf <= rx;
  rxfall <= rxbuf & (~rx);
end

////////////////////////////////////////////////////////////////
//啓動串口接收程序
////////////////////////////////////////////////////////////////
always @(posedge clk)
begin
  if (rxfall && (~idle)) begin//檢測到線路的下降沿並且原先線路爲空閒,啓動接收數據進程  
    receive <= 1'b1;
  end
  else if(cnt == 8'd168) begin //接收數據完成
    receive <= 1'b0;
  end
end

////////////////////////////////////////////////////////////////
//串口接收程序, 16個時鐘接收一個bit
////////////////////////////////////////////////////////////////
always @(posedge clk or negedge rst_n)
begin
  if (!rst_n) begin
     idle<=1'b0;
	  cnt<=8'd0;
     rdsig <= 1'b0;	 
	  frameerror <= 1'b0; 
	  dataerror <= 1'b0;	  
	  presult<=1'b0;
  end	  
  else if(receive == 1'b1) begin
		case (cnt)
		8'd0:begin
			idle <= 1'b1;
			cnt <= cnt + 8'd1;
			rdsig <= 1'b0;
		end
		8'd24:begin                 //接收第0位數據
			idle <= 1'b1;
			dataout[0] <= rx;
			presult <= paritymode^rx;
			cnt <= cnt + 8'd1;
			rdsig <= 1'b0;
		end
		8'd40:begin                 //接收第1位數據  
			idle <= 1'b1;
			dataout[1] <= rx;
			presult <= presult^rx;
			cnt <= cnt + 8'd1;
			rdsig <= 1'b0;
		end
		8'd56:begin                 //接收第2位數據   
			idle <= 1'b1;
			dataout[2] <= rx;
			presult <= presult^rx;
			cnt <= cnt + 8'd1;
			rdsig <= 1'b0;
		end
		8'd72:begin               //接收第3位數據   
			idle <= 1'b1;
			dataout[3] <= rx;
			presult <= presult^rx;
			cnt <= cnt + 8'd1;
			rdsig <= 1'b0;
		end
		8'd88:begin               //接收第4位數據    
			idle <= 1'b1;
			dataout[4] <= rx;
			presult <= presult^rx;
			cnt <= cnt + 8'd1;
			rdsig <= 1'b0;
		end
		8'd104:begin            //接收第5位數據    
			idle <= 1'b1;
			dataout[5] <= rx;
			presult <= presult^rx;
			cnt <= cnt + 8'd1;
			rdsig <= 1'b0;
		end
		8'd120:begin            //接收第6位數據    
			idle <= 1'b1;
			dataout[6] <= rx;
			presult <= presult^rx;
			cnt <= cnt + 8'd1;
			rdsig <= 1'b0;
		end
		8'd136:begin            //接收第7位數據   
			idle <= 1'b1;
			dataout[7] <= rx;
			presult <= presult^rx;
			cnt <= cnt + 8'd1;
			rdsig <= 1'b1;
		end
		8'd152:begin            //接收奇偶校驗位    
			idle <= 1'b1;
			if(presult == rx)
			  dataerror <= 1'b0;
			else
			  dataerror <= 1'b1;       //如果奇偶校驗位不對,表示數據出錯
			cnt <= cnt + 8'd1;
			rdsig <= 1'b1;
		end
		8'd168:begin
		  idle <= 1'b1;
		  if(1'b1 == rx)
			 frameerror <= 1'b0;
		  else
			 frameerror <= 1'b1;      //如果沒有接收到停止位,表示幀出錯
		  cnt <= cnt + 8'd1;
		  rdsig <= 1'b1;
		end
		default: begin
			cnt <= cnt + 8'd1;
		end
		endcase
   end	
   else begin
	  cnt <= 8'd0;
	  idle <= 1'b0;
	  rdsig <= 1'b0;	 
	end
end
endmodule

上面四個模塊都是黑金提供的,程序比較簡單所以也不用進行詳細說明,基本能對模塊進行仿真,並且

能在硬件上運行就差不多了

分配管腳

點擊工具欄快捷按鈕進行編譯

找到編譯後生成的sof文件,點擊Open添加進來

將sof文件下載到開發板

連接開發板的串口,發送數據12,可以看到,每發送一次12開發板也同樣會將接收到的12這個數據發出來

(這個串口比較簡單,只需瞭解一下原理,並且仿真出來,再在硬件上測試成功就可以了,不用花大

量時間,來進行驗證測試,這裏僅記錄一些簡單的步驟)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章