3.4 UART串口仿真實例
下面將對串口的RTL設計進行仿真測試。在前面的例子中,可以看出仿真的行為主要在testbench文件中定義。下面我們將為串口收發模塊rxtx.v寫一個testbench文件。如下所示: - `timescale 1 ns/1 ns
- module tb;
-
- reg clk = 1'b0;
- always clk = #20 ~clk;
-
- reg rst = 1'b1;
- initial #40 rst = 1'b0;
-
- reg RxD = 1'b1;
- reg tx_vld = 1'b0;
- reg [7:0] tx_data = 8'h0;
-
- wire rx_vld ;
- wire [7:0] rx_data ;
- wire TxD;
- wire txrdy;
-
- rxtx u_rxtx (
- .clk ( clk ),
- .rst ( rst ),
- .rx ( RxD ),
- .tx_vld ( tx_vld ),
- .tx_data ( tx_data ),
-
- .rx_vld ( rx_vld ),
- .rx_data ( rx_data ),
- .tx ( TxD ),
- .txrdy ( txrdy )
- );
在這里,我們采用同樣的方式例化rxtx。將rxtx的3個輸入信號RxD、tx_vld、tx_data定義為reg類型,并賦給初值。而對輸出rx_vld、rx_data、TxD、txrdy采用wire類型,表示把輸出信號引出來,共testbench使用。
接下來,定義一個task以傳送串行數據給RxD。task是在Verilog描述testbench經常用到的一種手段。它和function不同,它不需要返回數據。通過定義一個輸入input [7:0] b; 可以讓調用這個task時,賦給一個變量到b。然后RxD在發送串行數據時,采用b作為發送字節。這個task按照串口的格式把字節b送給RxD。它的周期是:104 167 ns(1/9600秒)。
- task rx_send;
- input [7:0] b;
- integer i;
- begin
- RxD = 1'b0;
- for (i=0;i<8;ii=i+1)
- #104167 RxD = b[i];
- #104167 RxD = ^b;
- #104167 RxD = 1'b1;
- #104167 RxD = 1'b1;
- end
- endtask
在這里,外面定義的reg類型RxD可以通過task內部直接調用,于是我們通過這個rx_send的task,可以把一個字節通過RxD串行發送出去。
另外一個task是采用同樣的方式給tx_vld和tx_data賦值。觸發rxtx模塊發送數據。在最開始,它必須等待txrdy為高電平。然后為tx_vld賦值一個周期的高電平。
- task tx_byte;
- input [7:0] b;
- begin
- while (~txrdy)
- @(posedge clk);
- @(posedge clk);
- #3 tx_vld = 1'b1;
- tx_data = b;
- @(posedge clk);
- #3 tx_vld = 1'b0;
- tx_data = 8'b0;
- end
- endtask
前面這兩個task是用來給rxtx產生激勵的。那么還需要對rxtx的輸出進行檢測。對于rx_vld和rx_data的檢測如下:- always @ (posedge clk )
- if (rx_vld)
- $display("--A byte: %2h received...",rx_data);
- else;
我們希望一旦rx_vld為高電平,即把接收的字節數據打印出來。
接下來,檢測TxD,確認它是否發送的是tx_data。我們通過TxD的下降沿觸發檢測流程。一旦探測到TxD的下降沿,即延時到半個周期,檢測起始0 bit是否有效。然后,對TxD傳送的數據和奇偶校驗位進行保存。在檢測完結束1 bit后,對檢測結果進行打印。- integer i;
- reg [7:0] rec_byte;
- reg oddeven;
- always @ (negedge TxD) begin
- #52080 if (TxD!=1'b0) $display("--Start bit error.");
- for (i=0;i<8;ii=i+1)
- #104167 rec_byte[i] = TxD;
- #104167 oddeven = TxD;
- #104167 if (TxD!=1'b1) $display("--End bit error.");
- #52080 $display("--A byte : %2h transmitted...",rec_byte);
- if (oddeven!=^rec_byte) $display("--Odd even error.");
- end
好了,如果我們再加上調用這兩個task的initial語句,則會顯示出檢測結果。- initial begin
- #100 tb.rx_send(8'h5a);
- tb.tx_byte(8'ha5);
- #2000000 $stop;
- end
- 在Transcript窗口中,顯示檢測結果如下:
- # --A byte: 5a received...
- # --A byte: a5 transmitted...
【責任編輯: book TEL:(010)68476606】
|