0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線(xiàn)課程
  • 觀(guān)看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

基于FIFO的串口發(fā)送機(jī)設(shè)計(jì)全流程

FPGA之家 ? 來(lái)源:FPGA之家 ? 作者:FPGA之家 ? 2022-04-25 09:38 ? 次閱讀

Verliog語(yǔ)法基礎(chǔ)

基本的語(yǔ)法略過(guò),主要想寫(xiě)一些關(guān)于框架,規(guī)范,技術(shù)難點(diǎn)的博文,這樣對(duì)于我們養(yǎng)成好的編碼習(xí)慣是有好處的,就定這樣一個(gè)flag吧.希望大家可以一起好好學(xué)習(xí),共同進(jìn)步.

接口時(shí)序設(shè)計(jì)規(guī)范

模塊和模塊之間的通過(guò)模塊的接口實(shí)現(xiàn)關(guān)聯(lián), 因此規(guī)范的時(shí)序設(shè)計(jì), 對(duì)于程序設(shè)計(jì)的過(guò)程, 以及程序的維護(hù), 團(tuán)隊(duì)之間的溝通都是非常必要的。

f6ff1376-c42c-11ec-bce3-dac502259ad0.jpg

命名規(guī)則

1、 頂層文件

對(duì)象+功能+top

比如:video_oneline_top

2、 邏輯控制文件

介于頂層和驅(qū)動(dòng)層文件之間

對(duì)象+ctr

比如:ddr_ctr.v


3、 驅(qū)動(dòng)程序命名

對(duì)象+功能+dri

比如:lcd_dri.v、 uart_rxd_dri.v


4、 參數(shù)文件命名

對(duì)象+para

比如:lcd_para.v


5、 模塊接口命名:文件名+u

比如 lcd_dir lcd_dir_u(........)


6、 模塊接口命名:特征名+文件名+u

比如 mcb_read c3_mcb_read_u


7、 程序注釋說(shuō)明

/*****************************************************************/

// Company:

// Engineer:

// WEB:

// BBS:

// Create Date: 0750 07/31/2019

// Design Name: FPGA STREAM

// Module Name: FPGA_USB

// Project Name: FPGA STREAM

// Target Devices: XC6SLX16-FTG256/XC6SLX25-FTG256 Mis603

// Tool versions: ISE14.7

// Description: CY7C68013A SLAVE FIFO comunication with fpga

// Revision: V1.0

// Additional Comments:

//1) _i input

//2) _o output

//3) _n activ low

//4) _dg debug signal

//5) _r delay or register

//6) _s state mechine

/*****************************************************************/

8、 端口注釋 input Video_vs_i,//輸入場(chǎng)同步入

9、 信號(hào)命名 命名總體規(guī)則:對(duì)象+功能(+極性) +特性

10、 時(shí)鐘信號(hào) 對(duì)象+功能+特性 比如:phy_txclk_i、 sys_50mhz_i

11、 復(fù)位信號(hào) 對(duì)象+功能+極性+特性 比如:phy_rst_n_i、 sys_rst_n_i

12、 延遲信號(hào) 對(duì)象+功能+特性 1+特征 2 比如:fram_sync_i_r0、 fram_sync_i_r1

13、 特定功能計(jì)數(shù)器

對(duì)象+cnt 比如:line_cnt、 div_cnt0、 div_cnt1 功能+cnt 比如:wr_cnt、 rd_cnt 對(duì)象+功能+cnt 比如:fifo_wr_cnt、 mcb_wr_cnt、 mem_wr_cnt 對(duì)象+對(duì)象+cnt 比如:video_line_cnt、 video_fram_cnt

14、 一般計(jì)數(shù)器 cnt+序號(hào) 用于不容易混淆的計(jì)數(shù) 比如:cnt0、 cnt1、 cnt2

15、 時(shí)序同步信號(hào) 對(duì)象+功能+特性 比如:line_sync_i、 fram_sysc_i

16、 使能信號(hào) 功能+en 比如:wr_en、 rd_en 對(duì)象+功能+en 比如:fifo_wr_en、 mcb_wr_en

Verilog 最最基礎(chǔ)語(yǔ)法

C 語(yǔ)言和 Verilog 的關(guān)鍵詞和結(jié)構(gòu)對(duì)比:

f70be056-c42c-11ec-bce3-dac502259ad0.jpg

C 語(yǔ)言和 Verilog 運(yùn)算符對(duì)比:

f71a8c78-c42c-11ec-bce3-dac502259ad0.jpg

關(guān)鍵字

信號(hào)部分:input 關(guān)鍵詞, 模塊的輸入信號(hào), 比如 input Clk, Clk 是外面關(guān)鍵輸入的時(shí)鐘信號(hào);

output 關(guān)鍵詞, 模塊的輸出信號(hào), 比如 output[3:0]Led; 這個(gè)地方正好是一組輸出信號(hào)。其中[3:0]表示 0~3 共 4 路信號(hào)。

inout 模塊輸入輸出雙向信號(hào)。這種類(lèi)型, 我們的例子 24LC02 中有使用。數(shù)總線(xiàn)的通信中, 這種信號(hào)被廣泛應(yīng)用;

wire 關(guān)鍵詞, 線(xiàn)信號(hào)。例如:wire C1_Clk; 其中 C1_Clk 就是 wire 類(lèi)型的信號(hào);

線(xiàn)信號(hào),三態(tài)類(lèi)型, 我們一般常用的線(xiàn)信號(hào)類(lèi)型有input,output,inout,wire;

reg 關(guān)鍵詞, 寄存器。和線(xiàn)信號(hào)不同, 它可以在 always 中被賦值, 經(jīng)常用于時(shí)序邏輯中。比如 reg[3:0]Led;表示了一組寄存器。

結(jié)構(gòu)部分:

module()… endmodule

代表一個(gè)模塊, 我們的代碼寫(xiě)在這個(gè)兩個(gè)關(guān)鍵字中間

always@()括號(hào)里面是敏感信號(hào)。這里的 always@(posedge Clk)敏感信號(hào)是 posedge Clk 含義是在上升沿的時(shí)候有效, 敏感信號(hào)還可以 negedge Clk 含義是下降沿的時(shí)候有效, 這種形式一般時(shí)序邏輯都會(huì)用到。還可以是*這個(gè)一符號(hào), 如果是一個(gè)*則表示一直是敏感的, 一般用于組合邏輯。

assign 用來(lái)給 output,inout 以及 wire 這些類(lèi)型進(jìn)行連線(xiàn)。assign 相當(dāng)于一條連線(xiàn), 將表達(dá)式右邊的電路直接通過(guò) wire(線(xiàn))連接到左邊, 左邊信號(hào)必須是 wire 型(output 和 inout 屬于 wire 型) 。當(dāng)右邊變化了左邊立馬變化, 方便用來(lái)描述簡(jiǎn)單的組合邏輯。

符號(hào)部分:

這里重點(diǎn)講解一下“<=” 賦值符號(hào),非阻塞賦值?,“=” 阻塞賦值,“{}”

“<=” 賦值符號(hào), 非阻塞賦值, 在一個(gè) always 模塊中, 所有語(yǔ)句一起更新。它也可以表示小于等于, 具體是什么含義編譯環(huán)境根據(jù)當(dāng)前編程環(huán)境判斷, 如果“<=” 是用在一個(gè) if 判斷里如:if(a <= 10);當(dāng)然就表示小于等于了。

“=” 阻塞賦值, 或者給信號(hào)賦值, 如果在 always 模塊中, 這條語(yǔ)句被立刻執(zhí)行。阻塞賦值和非阻塞賦值將再后面詳細(xì)舉例說(shuō)明。

“{} ” 在 Verilog 中表示拼接符, {a,b}這個(gè)的含義是將括號(hào)內(nèi)的數(shù)按位并在一起, 比如:{1001,1110}表示的是 10011110。拼接是 Verilog 相對(duì)于其他語(yǔ)言的一大優(yōu)勢(shì), 在以后的編程中請(qǐng)慢慢體會(huì)。

參數(shù)部分:

parameter



parameter a = 180;//十進(jìn)制, 默認(rèn)分配長(zhǎng)度 32bit(編譯器默認(rèn))parameter a = 8’d180;//十進(jìn)制parameter a = 8’haa; //十六進(jìn)制parameter a = 8’b1010_1010; //二進(jìn)制

預(yù)處理命令

`include file1.v`define X = 1;`deine Y;`ifdef YZ=1;`elseZ=0;`endif

Verilog 中數(shù)值表示的方式

如果我們要表示一個(gè)十進(jìn)制是 180 的數(shù)值, 在 Verilog 中的表示方法如下:

二進(jìn)制:8’ b1010_1010; //其中“_” 是為了容易觀(guān)察位數(shù), 可有可無(wú)。

十進(jìn)制:8’ d180;

16 進(jìn)制:8’ hAA;

講到這里,具備這些基礎(chǔ)知識(shí),需要通過(guò)代碼來(lái)學(xué)習(xí)Veriog 語(yǔ)言。最后, 筆者提一點(diǎn)建議, 學(xué)習(xí) Verilog 多看別人寫(xiě)的優(yōu)秀的代碼, 多看官方提供的代碼和文檔。其中官方提供的代碼, 很多時(shí)候代表了最新的用法, 或者推薦的用法。讀者學(xué)習(xí), 首先把最最基礎(chǔ)的掌握好, 這樣, 在項(xiàng)目中遇到了問(wèn)題, 也能快速學(xué)習(xí), 快速解決。

對(duì)于理論知識(shí)的學(xué)習(xí), 沒(méi)必要一開(kāi)始就研究得那么深刻, 只是搞理論學(xué)習(xí), 對(duì)于學(xué)習(xí)Verilog 語(yǔ)言, 或者 FPGA 開(kāi)發(fā)是不實(shí)際的, 要聯(lián)系理論和實(shí)踐結(jié)合。多仿真, 多驗(yàn)證, 多問(wèn)題, 多學(xué)習(xí), 多改進(jìn).

淺談狀態(tài)機(jī)

01. 前言

狀態(tài)機(jī)是FPGA設(shè)計(jì)中一種非常重要、非常根基的設(shè)計(jì)思想,堪稱(chēng)FPGA的靈魂,貫穿FPGA設(shè)計(jì)的始終。

02.狀態(tài)機(jī)簡(jiǎn)介

什么是狀態(tài)機(jī):狀態(tài)機(jī)通過(guò)不同的狀態(tài)遷移來(lái)完成特定的邏輯操作(時(shí)序操作)狀態(tài)機(jī)是許多數(shù)字系統(tǒng)的核心部件, 是一類(lèi)重要的時(shí)序邏輯電路。通常包括三個(gè)部分:

  • 下一個(gè)狀態(tài)的邏輯電路

  • 存儲(chǔ)狀態(tài)機(jī)當(dāng)前狀態(tài)的時(shí)序邏輯電路

  • 輸出組合邏輯電路

03. 狀態(tài)機(jī)分類(lèi)

通常, 狀態(tài)機(jī)的狀態(tài)數(shù)量有限, 稱(chēng)為有限狀態(tài)機(jī)(FSM) 。由于狀態(tài)機(jī)所有觸發(fā)器的時(shí)鐘由同一脈沖邊沿觸發(fā), 故也稱(chēng)之為同步狀態(tài)機(jī)。

根據(jù)狀態(tài)機(jī)的輸出信號(hào)是否與電路的輸入有關(guān)分為 Mealy 型狀態(tài)機(jī)和 Moore 型狀態(tài)機(jī)

3.1,Mealy 型狀態(tài)機(jī)

電路的輸出信號(hào)不僅與電路當(dāng)前狀態(tài)有關(guān), 還與電路的輸入有關(guān)

f72a987a-c42c-11ec-bce3-dac502259ad0.jpg

3.2,Moore 型狀態(tài)機(jī)

電路的輸出僅僅與各觸發(fā)器的狀態(tài), 不受電路輸入信號(hào)影響或無(wú)輸入

f735783a-c42c-11ec-bce3-dac502259ad0.jpg

狀態(tài)機(jī)的狀態(tài)轉(zhuǎn)移圖, 通常也可根據(jù)輸入和內(nèi)部條件畫(huà)出。一般來(lái)說(shuō), 狀態(tài)機(jī)的設(shè)計(jì)包含下列設(shè)計(jì)步驟:

  • 根據(jù)需求和設(shè)計(jì)原則, 確定是 Moore 型還是 Mealy 型狀態(tài)機(jī);

  • 分析狀態(tài)機(jī)的所有狀態(tài), 對(duì)每一狀態(tài)選擇合適的編碼方式, 進(jìn)行編碼;

  • 根據(jù)狀態(tài)轉(zhuǎn)移關(guān)系和輸出繪出狀態(tài)轉(zhuǎn)移圖;

  • 構(gòu)建合適的狀態(tài)機(jī)結(jié)構(gòu), 對(duì)狀態(tài)機(jī)進(jìn)行硬件描述。

04. 狀態(tài)機(jī)描述

狀態(tài)機(jī)的描述通常有三種方法, 稱(chēng)為一段式狀態(tài)機(jī), 二段式狀態(tài)機(jī)和三段式狀態(tài)機(jī)。


狀態(tài)機(jī)的描述通常包含以下四部分:

  • 利用參數(shù)定義語(yǔ)句 parameter 描述狀態(tài)機(jī)各個(gè)狀態(tài)名稱(chēng), 即狀態(tài)編碼。狀態(tài)編碼通常有很多方法包含自然二進(jìn)制編碼, One-hot 編碼,格雷編碼碼等;

  • 用時(shí)序的 always 塊描述狀態(tài)觸發(fā)器實(shí)現(xiàn)狀態(tài)存儲(chǔ);

  • 使用敏感表和 case 語(yǔ)句(也采用 if-else 等價(jià)語(yǔ)句) 描述狀態(tài)轉(zhuǎn)換邏輯;

  • 描述狀態(tài)機(jī)的輸出邏輯。

下面根據(jù)狀態(tài)機(jī)的三種方法來(lái)具體說(shuō)明

4.1,一段式狀態(tài)機(jī)

module detect_1(

input clk_i,

input rst_n_i,

output out_o

);

reg out_r;

//狀態(tài)聲明和狀態(tài)編碼

reg [1:0] state;

parameter [1:0] S0=2‘b00;

parameter [1:0] S1=2’b01;

parameter [1:0] S2=2‘b10;

parameter [1:0] S3=2’b11;

always@(posedge clk_i)

begin

if(!rst_n_i)begin

state《=0;

out_r《=1‘b0;

end

else

case(state)

S0 :

begin

out_r《=1’b0;

state《= S1;

end

S1 :

begin

out_r《=1‘b1;

state《= S2;

end

S2 :

begin

out_r《=1’b0;

state《= S3;

end

S3 :

begin

out_r《=1‘b1;

end

endcase

end

assign out_o=out_r;

endmodul

一段式狀態(tài)機(jī)是應(yīng)該避免使用的, 該寫(xiě)法僅僅適用于非常簡(jiǎn)單的狀態(tài)機(jī)設(shè)計(jì)。

4.2,兩段式狀態(tài)機(jī)

module detect_2(

input clk_i,

input rst_n_i,

output out_o

);

reg out_r;

//狀態(tài)聲明和狀態(tài)編碼

reg [1:0] Current_state;

reg [1:0] Next_state;

parameter [1:0] S0=2‘b00;

parameter [1:0] S1=2’b01;

parameter [1:0] S2=2‘b10;

parameter [1:0] S3=2’b11;

//時(shí)序邏輯:描述狀態(tài)轉(zhuǎn)換

always@(posedge clk_i)

begin

if(!rst_n_i)

Current_state《=0;

else

Current_state《=Next_state;

end

//組合邏輯:描述下一狀態(tài)和輸出

always@(*)

begin

out_r=1‘b0;

case(Current_state)

S0 :

begin

out_r=1’b0;

Next_state= S1;

end

S1 :

begin

out_r=1‘b1;

Next_state= S2;

end

S2 :

begin

out_r=1’b0;

Next_state= S3;

end

S3 :

begin

out_r=1‘b1;

Next_state=Next_state;

end

endcase

end

assign out_o = out_r;

endmodule

兩段式狀態(tài)機(jī)采用兩個(gè) always 模塊實(shí)現(xiàn)狀態(tài)機(jī)的功能, 其中一個(gè) always 采用同步時(shí)序邏輯描述狀態(tài)轉(zhuǎn)移, 另一個(gè) always 采用組合邏輯來(lái)判斷狀態(tài)條件轉(zhuǎn)移。

4.3,三段式狀態(tài)機(jī)

module detect_3(

input clk_i,

input rst_n_i,

output out_o

);

reg out_r;

//狀態(tài)聲明和狀態(tài)編碼

reg [1:0] Current_state;

reg [1:0] Next_state;

parameter [1:0] S0=2‘b00;

parameter [1:0] S1=2’b01;

parameter [1:0] S2=2‘b10;

parameter [1:0] S3=2’b11;

//時(shí)序邏輯:描述狀態(tài)轉(zhuǎn)換

always@(posedge clk_i)

begin

if(!rst_n_i)

Current_state《=0;

else

Current_state《=Next_state;

end

//組合邏輯:描述下一狀態(tài)

always@(*)

begin

case(Current_state)

S0:

Next_state = S1;

S1:

Next_state = S2;

S2:

Next_state = S3;

S3:

begin

Next_state = Next_state;

end

default :

Next_state = S0;

endcase

end

//輸出邏輯: 讓輸出 out, 經(jīng)過(guò)寄存器 out_r 鎖存后輸出, 消除毛刺

always@(posedge clk_i)

begin

if(!rst_n_i)

out_r《=1‘b0;

else

begin

case(Current_state)

S0,S2:

out_r《=1’b0;

S1,S3:

out_r《=1‘b1;

default :

out_r《=out_r;

endcase

end

end

assign out_o=out_r;

endmodule

三段式狀態(tài)機(jī)在第一個(gè) always 模塊采用同步時(shí)序邏輯方式描述狀態(tài)轉(zhuǎn)移, 第二個(gè)always 模塊采用組合邏輯方式描述狀態(tài)轉(zhuǎn)移規(guī)律, 第三個(gè) always 描述電路的輸出。通常讓輸出信號(hào)經(jīng)過(guò)寄存器緩存之后再輸出, 消除電路毛刺。

05. 狀態(tài)機(jī)優(yōu)缺點(diǎn)

1、一段式狀態(tài)機(jī):只涉及時(shí)序電路,沒(méi)有競(jìng)爭(zhēng)與冒險(xiǎn),同時(shí)消耗邏輯比較少。

但是如果狀態(tài)非常多,一段式狀態(tài)機(jī)顯得比較臃腫,不利于維護(hù)。

2、兩段式狀態(tài)機(jī):當(dāng)一個(gè)模塊采用時(shí)序(狀態(tài)轉(zhuǎn)移),一個(gè)模塊采用組合時(shí)候(狀態(tài)機(jī)輸出),組合邏輯電路容易造成競(jìng)爭(zhēng)與冒險(xiǎn);當(dāng)兩個(gè)模塊都采用時(shí)序,可以避免競(jìng)爭(zhēng)與冒險(xiǎn)的存在,但是整個(gè)狀態(tài)機(jī)的時(shí)序上會(huì)延時(shí)一個(gè)周期。

兩段式狀態(tài)機(jī)是推薦的狀態(tài)機(jī)設(shè)計(jì)方法。

3、三段式狀態(tài)機(jī):三段式狀態(tài)機(jī)在狀態(tài)轉(zhuǎn)移時(shí)采用組合邏輯電路+格雷碼,避免了組合邏輯的競(jìng)爭(zhēng)與冒險(xiǎn);狀態(tài)機(jī)輸出采用了同步寄存器輸出,也可以避免組合邏輯電路的競(jìng)爭(zhēng)與冒險(xiǎn);采用這兩種方法極大的降低了競(jìng)爭(zhēng)冒險(xiǎn)。并且在狀態(tài)機(jī)的采用這種組合邏輯電路+次態(tài)寄存器輸出,避免了兩段式狀態(tài)機(jī)的延時(shí)一個(gè)周期(三段式狀態(tài)機(jī)在上一狀態(tài)中根據(jù)輸入條件判斷當(dāng)前狀態(tài)的輸出,從而在不插入額外時(shí)鐘節(jié)拍的前提下,實(shí)現(xiàn)寄存器的輸出)。

三段式狀態(tài)機(jī)也是比較推崇的,主要是由于維護(hù)方便, 組合邏輯與時(shí)序邏輯完全獨(dú)立。

06. 總結(jié)

靈活選擇狀態(tài)機(jī),不一定要拘泥理論,怎樣方便怎樣來(lái)

07.擴(kuò)展

四段式不是指三個(gè)always代碼,而是四段程序。使用四段式的寫(xiě)法,可參照明德?lián)PGVIM特色指令Ztj產(chǎn)生的狀態(tài)機(jī)模板。

明·德·揚(yáng)四段式狀態(tài)機(jī)符合一次只考慮一個(gè)因素的設(shè)計(jì)理念。

  • 第一段代碼,照抄格式,完全不用想其他的。

  • 第二段代碼,只考慮狀態(tài)之間的跳轉(zhuǎn),也就是說(shuō)各個(gè)狀態(tài)機(jī)之間跳轉(zhuǎn)關(guān)系。

  • 第三段代碼,只考慮跳轉(zhuǎn)條件。

  • 第四段,每個(gè)信號(hào)逐個(gè)設(shè)計(jì)。

Test bench文件結(jié)構(gòu)一覽無(wú)余

01,前言

Verilog測(cè)試平臺(tái)是一個(gè)例化的待測(cè)(MUT)模塊,重要的是給它施加激勵(lì)并觀(guān)測(cè)其輸出。邏輯模塊與其對(duì)應(yīng)的測(cè)試平臺(tái)共同組成仿真模型,應(yīng)用這個(gè)模型可以測(cè)試該模塊能否符合自己的設(shè)計(jì)要求。

編寫(xiě)TESTBENCH的目的是為了對(duì)使用硬件描述語(yǔ)言設(shè)計(jì)的電路進(jìn)行仿真驗(yàn)證,測(cè)試設(shè)計(jì)電路的功能、性能與設(shè)計(jì)的預(yù)期是否相符。通常,編寫(xiě)測(cè)試文件的過(guò)程如下:

  • 產(chǎn)生模擬激勵(lì)(波形);

  • 將產(chǎn)生的激勵(lì)加入到被測(cè)試模塊中并觀(guān)察其響應(yīng);

  • 將輸出響應(yīng)與期望值相比較。

02,完成的Test bench文件結(jié)構(gòu)

通常,一個(gè)完整的測(cè)試文件其結(jié)構(gòu)為

  • module Test_bench();//通常無(wú)輸入無(wú)輸出

  • 信號(hào)或變量聲明定義

  • 邏輯設(shè)計(jì)中輸入對(duì)應(yīng)reg型

  • 邏輯設(shè)計(jì)中輸出對(duì)應(yīng)wire型

  • 使用initial或always語(yǔ)句產(chǎn)生激勵(lì)

  • 例化待測(cè)試模塊

  • 監(jiān)控和比較輸出響應(yīng)

  • endmodule

03,時(shí)鐘激勵(lì)設(shè)計(jì)

下面列舉出一些常用的封裝子程序, 這些是常用的寫(xiě)法, 在很多應(yīng)用中都能用到。

3.1,時(shí)鐘激勵(lì)產(chǎn)生方法一

50%占空比時(shí)鐘

parameterClockPeriod=10;initialbeginclk_i=0;forever#(ClockPeriod/2)clk_i=~clk_i;end

3.2,時(shí)鐘激勵(lì)產(chǎn)生方法二

50%占空比時(shí)鐘

initialbeginclk_i=0;always#(ClockPeriod/2)clk_i=~clk_i;end

3.3,時(shí)鐘激勵(lì)產(chǎn)生方法三:

產(chǎn)生固定數(shù)量的時(shí)鐘脈沖


initialbeginclk_i=0;repeat(6)#(ClockPeriod/2)clk_i=~clk_i;end

3.4,時(shí)鐘激勵(lì)產(chǎn)生方法四

產(chǎn)生非占空比為50%的時(shí)鐘

initialbeginclk_i=0;foreverbegin#((ClockPeriod/2)-2)clk_i=0;#((ClockPeriod/2)+2)clk_i=1;end

04,復(fù)位信號(hào)設(shè)計(jì)

4.1,復(fù)位信號(hào)產(chǎn)生方法一

異步復(fù)位

initialbeginrst_n_i=1;#100;rst_n_i=0;#100;rst_n_i=1;end

4.2,復(fù)位信號(hào)產(chǎn)生方法二

同步復(fù)位

initialbeginrst_n_i=1;@(negedgeclk_i)rst_n_i=0;#100;//固定時(shí)間復(fù)位repeat(10)@(negedgeclk_i);//固定周期數(shù)復(fù)位@(negedgeclk_i)rst_n_i=1;end

4.3復(fù)位信號(hào)產(chǎn)生方法三

復(fù)位任務(wù)封裝

taskreset;input[31:0]reset_time;//復(fù)位時(shí)間可調(diào),輸入復(fù)位時(shí)間RST_ING=0;//復(fù)位方式可調(diào),低電平或高電平beginrst_n=RST_ING;//復(fù)位中#reset_time;//復(fù)位時(shí)間rst_n_i=~RST_ING;//撤銷(xiāo)復(fù)位,復(fù)位結(jié)束endendtask

05,雙向信號(hào)設(shè)計(jì)

5.1,雙向信號(hào)描述一

inout在testbench中定義為wire型變量

//為雙向端口設(shè)置中間變量inout_reg作為inout的輸出寄存,其中inout變//量定義為wire型,使用輸出使能控制傳輸方向//inoutbir_port;wirebir_port;regbir_port_reg;regbi_port_oe;assignbi_port=bi_port_oe?bir_port_reg:1'bz;

5.2雙向信號(hào)描述二

強(qiáng)制force

//當(dāng)雙向端口作為輸出口時(shí),不需要對(duì)其進(jìn)行初始化,而只需開(kāi)通三態(tài)門(mén)//當(dāng)雙向端口作為輸入時(shí),只需要對(duì)其初始化并關(guān)閉三態(tài)門(mén),初始化賦值需//使用wire型數(shù)據(jù),通過(guò)force命令來(lái)對(duì)雙向端口進(jìn)行輸入賦值//assigndinout=(!en)din:16'hz;完成雙向賦值initialbeginforcedinout=20;#200forcedinout=dinout-1;end

06,特殊信號(hào)設(shè)計(jì)

6.1特殊激勵(lì)信號(hào)產(chǎn)生描述一

輸入信號(hào)任務(wù)封裝

taski_data;input[7:0]dut_data;begin@(posedgedata_en);send_data=0;@(posedgedata_en);send_data=dut_data[0];@(posedgedata_en);send_data=dut_data[1];@(posedgedata_en);send_data=dut_data[2];@(posedgedata_en);send_data=dut_data[3];@(posedgedata_en);send_data=dut_data[4];@(posedgedata_en);send_data=dut_data[5];@(posedgedata_en);send_data=dut_data[6];@(posedgedata_en);send_data=dut_data[7];@(posedgedata_en);send_data=1;#100;endendtask//調(diào)用方法:i_data(8'hXX);

6.2特殊激勵(lì)信號(hào)產(chǎn)生描述二

多輸入信號(hào)任務(wù)封裝

taskmore_input;input[7:0]a;input[7:0]b;input[31:0]times;output[8:0]c;beginrepeat(times)//等待times個(gè)時(shí)鐘上升沿@(posedgeclk_i)c=a+b;//時(shí)鐘上升沿a,b相加endendtask//調(diào)用方法:more_input(x,y,t,z);//按聲明順序

6.3,特殊激勵(lì)信號(hào)產(chǎn)生描述三

輸入信號(hào)產(chǎn)生,一次SRAM寫(xiě)信號(hào)產(chǎn)生

initialbegincs_n=1;//片選無(wú)效wr_n=1;//寫(xiě)使能無(wú)效rd_n=1;//讀使能無(wú)效addr=8'hxx;//地址無(wú)效data=8'hzz;//數(shù)據(jù)無(wú)效#100;cs_n=0;//片選有效wr_n=0;//寫(xiě)使能有效addr=8'hF1;//寫(xiě)入地址data=8'h2C;//寫(xiě)入數(shù)據(jù)#100;cs_n=1;wr_n=1;#10;addr=8'hxx;data=8'hzz;end

Testbench中@與wait

//@使用沿觸發(fā)//wait語(yǔ)句都是使用電平觸發(fā)initialbeginstart=1'b1;wait(en=1'b1);#10;start=1'b0;end

07,仿真控制語(yǔ)句及系統(tǒng)任務(wù)描述

7.1,仿真控制語(yǔ)句及系統(tǒng)任務(wù)描述

$stop//停止運(yùn)行仿真,modelsim中可繼續(xù)仿真$stop(n)//帶參數(shù)系統(tǒng)任務(wù),根據(jù)參數(shù)0,1或2不同,輸出仿真信息$finish//結(jié)束運(yùn)行仿真,不可繼續(xù)仿真$finish(n)//帶參數(shù)系統(tǒng)任務(wù),根據(jù)參數(shù)0,1或2不同,輸出仿真信息//0:不輸出任何信息//1:輸出當(dāng)前仿真時(shí)刻和位置//2:輸出當(dāng)前仿真時(shí)刻、位置和仿真過(guò)程中用到的memory以及CPU時(shí)間的統(tǒng)計(jì)$random//產(chǎn)生隨機(jī)數(shù)$random%n//產(chǎn)生范圍-n到n之間的隨機(jī)數(shù){$random}%n//產(chǎn)生范圍0到n之間的隨機(jī)數(shù)

?

7.2,仿真終端顯示描述

$monitor//仿真打印輸出,大印出仿真過(guò)程中的變量,使其終端顯示/*$monitor($time,,,"clk=%dreset=%dout=%d",clk,reset,out);*/$display//終端打印字符串,顯示仿真結(jié)果等/*$display(”Simulationstart!");$display(”Attime%t,inputis%b%b%b,outputis%b",$time,a,b,en,z);*/$time//返回64位整型時(shí)間$stime//返回32位整型時(shí)間$realtime//實(shí)行實(shí)型模擬時(shí)間

7.3文本輸入方式

$readmemb/$readmemh//激勵(lì)具有復(fù)雜的數(shù)據(jù)結(jié)構(gòu)//verilog提供了讀入文本的系統(tǒng)函數(shù)$readmemb/$readmemh("<數(shù)據(jù)文件名>",<存儲(chǔ)器名>);$readmemb/$readmemh("<數(shù)據(jù)文件名>",<存儲(chǔ)器名>,<起始地址>);$readmemb/$readmemh("<數(shù)據(jù)文件名>",<存儲(chǔ)器名>,<起始地址>,<結(jié)束地址>);$readmemb:/*讀取二進(jìn)制數(shù)據(jù),讀取文件內(nèi)容只能包含:空白位置,注釋行,二進(jìn)制數(shù)數(shù)據(jù)中不能包含位寬說(shuō)明和格式說(shuō)明,每個(gè)數(shù)字必須是二進(jìn)制數(shù)字。*/$readmemh:/*讀取十六進(jìn)制數(shù)據(jù),讀取文件內(nèi)容只能包含:空白位置,注釋行,十六進(jìn)制數(shù)數(shù)據(jù)中不能包含位寬說(shuō)明和格式說(shuō)明,每個(gè)數(shù)字必須是十六進(jìn)制數(shù)字。*//*當(dāng)?shù)刂烦霈F(xiàn)在數(shù)據(jù)文件中,格式為@hh...h,地址與數(shù)字之間不允許空白位置,可出現(xiàn)多個(gè)地址*/modulereg[7:0]memory[0:3];//聲明8個(gè)8位存儲(chǔ)單元integeri;initialbegin$readmemh("mem.dat",memory);//讀取系統(tǒng)文件到存儲(chǔ)器中的給定地址//顯示此時(shí)存儲(chǔ)器內(nèi)容for(i=0;i<4;i=i+1)$display("Memory[%d]=%h",i,memory[i]);endendmodule

?

/*mem.dat文件內(nèi)容

@001ABCD@003A1*/

//仿真輸出為

Memory[0]=xx;Memory[1]=AB;Memory[2]=CD;Memory[3]=A1;

08,總結(jié)

一個(gè)完整的設(shè)計(jì),除了好的功能描述代碼,對(duì)于程序的仿真驗(yàn)證是必不可少的。學(xué)會(huì)如何去驗(yàn)證自己所寫(xiě)的程序,即如何調(diào)試自己的程序是一件非常重要的事情。而RTL邏輯設(shè)計(jì)中,學(xué)會(huì)根據(jù)硬件邏輯來(lái)寫(xiě)測(cè)試程序,即Testbench是尤其重要的。

【很重要】Testbenth前仿真全過(guò)程

01. 前言

在FPGA 高手養(yǎng)成記-Test bench文件結(jié)構(gòu)一覽無(wú)余只是簡(jiǎn)單的例舉了常用的 testbench 寫(xiě)法,在工程應(yīng)用中基本能夠滿(mǎn)足我們需求, 至于其他更為復(fù)雜的 testbench 寫(xiě)法, 大家可參考其他書(shū)籍或資料。

testbench沒(méi)有像RTL代碼設(shè)計(jì)那樣嚴(yán)謹(jǐn),我們可以在符合語(yǔ)法規(guī)則的前提下,隨意編寫(xiě)我們的測(cè)試文件,有些在RTL代碼中不可綜合的語(yǔ)句,我們可以在testbench中實(shí)現(xiàn)。大體流程如下:

f74431a4-c42c-11ec-bce3-dac502259ad0.jpg

02.測(cè)試模塊設(shè)計(jì)

要測(cè)試我們的cpu需要ROM和RAM模塊,這就需要我們先做好這兩個(gè)模塊

f7533456-c42c-11ec-bce3-dac502259ad0.jpg

這里定義了一個(gè) 1024 x 8 的RAM

f75f713a-c42c-11ec-bce3-dac502259ad0.png

再定義一個(gè)8192x 8 的ROM

ROM和RAM都還沒(méi)有裝入數(shù)據(jù),等會(huì)我們會(huì)調(diào)用函數(shù)給他們裝數(shù)據(jù),接下來(lái)是地址譯碼器,來(lái)控制ROM和RAM的打開(kāi)與關(guān)閉。

f76dd77a-c42c-11ec-bce3-dac502259ad0.jpg

各模塊建立好之后我們就開(kāi)始仿真了。

03.仿真

這次教學(xué)我們用的是modelsim SE 10.0 版本進(jìn)行教學(xué),直接先在quartus II中建一個(gè).v文件將其保存在原來(lái)的工程文件目錄中,并命名為cpu_top.v,直接在這里寫(xiě)測(cè)試代碼

f77abd82-c42c-11ec-bce3-dac502259ad0.jpg

下面大家可以來(lái)完成cpu 的仿真過(guò)程了

3.1,模塊包含

首先,我們需要將我們剛寫(xiě)好的那幾個(gè)模塊包含進(jìn)去,即CPU模塊,ROM模塊,RAM模塊,地址譯碼器模塊,并寫(xiě)好時(shí)間測(cè)量度,見(jiàn)下圖

f785e3ec-c42c-11ec-bce3-dac502259ad0.jpg

3.2,定義頂層模塊
由于我們的設(shè)計(jì)只有兩個(gè)輸入,即時(shí)鐘模塊和復(fù)位模塊,凡是輸入信號(hào)在testbench中統(tǒng)一定義成reg型變量,凡是輸出或者雙向輸入輸出信號(hào)統(tǒng)一定義成wire型變量,我們的設(shè)計(jì)只有輸入沒(méi)有輸出,故只定義輸入和連線(xiàn)即可

f7933bfa-c42c-11ec-bce3-dac502259ad0.jpg

下圖便是我們要組成的測(cè)試頂層模塊圖,我們定義的wire型變量,實(shí)際就是我們頂層模塊中,模塊模塊與模塊間的連線(xiàn)。而這些連線(xiàn)就是我們cpu的輸出,這樣我們就可以用我們的測(cè)試模塊來(lái)測(cè)試我們的cpu是否能正確工作


f7a1f08c-c42c-11ec-bce3-dac502259ad0.jpg

3.3. 元件例化
就是將各個(gè)模塊連接起來(lái)即可,這里就不做太多的說(shuō)明了,因?yàn)橐郧岸紝?xiě)過(guò)很多次了
f7ae7b0e-c42c-11ec-bce3-dac502259ad0.jpg

3.4.測(cè)試激勵(lì)的書(shū)寫(xiě)
先寫(xiě)好時(shí)鐘產(chǎn)生模塊和復(fù)位模塊.并將復(fù)位模塊用task任務(wù)封裝,這樣我們?cè)跍y(cè)試過(guò)程中就可以隨時(shí)調(diào)用復(fù)位任務(wù)進(jìn)行復(fù)位

時(shí)鐘為50Mhz,復(fù)位時(shí)間為20ns

f7b9ccfc-c42c-11ec-bce3-dac502259ad0.jpg

然后,我們?cè)儆胻ask封裝我們需要的模塊,我們來(lái)想一下,上電后,CPU會(huì)從ROM中讀兩個(gè)時(shí)鐘周期的數(shù)據(jù)是吧,但是我們的ROM現(xiàn)在還是空的,所以我們需要一個(gè)任務(wù)是往ROM中裝入程序,給ROM中裝數(shù)據(jù)我們可以用系統(tǒng)函數(shù)$readmemb,即打開(kāi)一個(gè)文件,并將其中的數(shù)據(jù)送到我們之前定義的ROM中去

f7c692b6-c42c-11ec-bce3-dac502259ad0.jpg


而test1.pro文件是需要我們自己定義的,我們可以在quartusII中再新建一個(gè).v文件,在里面寫(xiě)上我們自己定義的程序,并將其保存為.pro文件即可,至于寫(xiě)什么程序,是我們隨便定義的.


f7d24af2-c42c-11ec-bce3-dac502259ad0.jpg

裝完ROM和RAM的數(shù)據(jù)之后,按說(shuō)就可以了進(jìn)行波形仿真了,因?yàn)閏pu是自動(dòng)讀取數(shù)據(jù)的,下面我們先來(lái)做第一步仿真,我先把之后的代碼注釋掉,大家先看沒(méi)有被注釋掉的代碼
f7e0974c-c42c-11ec-bce3-dac502259ad0.jpg


里面都是我們之前封裝好的函數(shù),剛開(kāi)始進(jìn)行復(fù)位,然后進(jìn)行第一步測(cè)試,之后停止,將其保存之后,并默認(rèn)為用其打開(kāi),打開(kāi)后見(jiàn)下圖


f7ecfc76-c42c-11ec-bce3-dac502259ad0.jpg

然后,file——new——library——ok即建好一個(gè)庫(kù)

f7fb271a-c42c-11ec-bce3-dac502259ad0.jpg


點(diǎn)擊左上角的編譯按鈕,將我們之前寫(xiě)好的所有.v文件全部都編譯進(jìn)去


f80cfd1e-c42c-11ec-bce3-dac502259ad0.jpg


看到transcript一欄顯示編譯成功后即可,若沒(méi)有transcript一欄,可以選擇菜單中的view——transcript即可,若顯示有紅色錯(cuò)誤,那就請(qǐng)讀者按照它的要求進(jìn)行修改代碼,這說(shuō)明你的代碼有問(wèn)題,一般是連接問(wèn)題

f81b1f66-c42c-11ec-bce3-dac502259ad0.jpg

3.5,波形仿真

編譯成功后,雙擊cpu_top就可以開(kāi)始波形仿真了

f829d236-c42c-11ec-bce3-dac502259ad0.jpg


進(jìn)入仿真頁(yè)面后,我們右擊cpu模塊將其加入至波形

f83a1574-c42c-11ec-bce3-dac502259ad0.jpg

大家先看兩個(gè)圖,等會(huì)結(jié)合這兩個(gè)圖給大家細(xì)細(xì)講解仿真過(guò)程

f84701ee-c42c-11ec-bce3-dac502259ad0.jpg

f85516c6-c42c-11ec-bce3-dac502259ad0.jpg


f860568a-c42c-11ec-bce3-dac502259ad0.jpg

我們先來(lái)看第一個(gè)過(guò)程

f86b8cc6-c42c-11ec-bce3-dac502259ad0.jpg

上電后,cpu先從ROM中讀回兩個(gè)周期的數(shù)據(jù),是從ROM的0地址開(kāi)始的,再對(duì)比我們之前定義好的ROM,數(shù)據(jù)讀取正確,讀回的數(shù)據(jù)的前三位是111,即指令碼JMP,后13位003c為地址碼,JMP指令是將讀回的數(shù)據(jù)作為新的地址碼來(lái)讀取相應(yīng)地址的數(shù)據(jù)。那么,下一步,cpu應(yīng)該是從ROM的003c地址處讀數(shù)據(jù)才對(duì),再看一下波形


f8786efa-c42c-11ec-bce3-dac502259ad0.jpg

對(duì)比波形后可知,cpu正好是從003c處讀取數(shù)據(jù),讀到的數(shù)據(jù)指令碼位111即JMP,地址碼位0006,再到ROM的0006地址處看

f8866014-c42c-11ec-bce3-dac502259ad0.jpg


這次讀回的指令碼位101,即LDA,也就是說(shuō)將后13位地址碼對(duì)應(yīng)的RAM中的數(shù)據(jù)讀回,送到累加器中,想一下,這時(shí)的RAM應(yīng)該是打開(kāi)的,而且雙向輸入輸出口的數(shù)據(jù)總線(xiàn)上應(yīng)該是來(lái)自RAM的8位數(shù)據(jù),由于ROM0006地址處的地址碼為1800是13位的,而RAM的地址是9位的,因此實(shí)際上我們從RAM中讀回的數(shù)據(jù)是從RAM的0地址讀回的,即我們之前給RAM寫(xiě)好的0000_0000,再看一下波形

f895632a-c42c-11ec-bce3-dac502259ad0.jpg


正如我們所想的一樣,數(shù)據(jù)總線(xiàn)上是0000_0000,RAM是打開(kāi)的,地址為1800

就這樣,讀者可以自己再試一下,看看我們的cpu是不是按照我們之前給他的程序運(yùn)行的,在這里我就不再給大家一一介紹了

雖然波形仿真很直觀(guān),但是看久了就會(huì)令人眼花繚亂,尤其是數(shù)據(jù)很多的時(shí)候,我們只能看其中一部分,不能講所有數(shù)據(jù)看完整,這時(shí)候我們單單是用波形來(lái)仿真就遠(yuǎn)遠(yuǎn)不夠了,下面介紹用系統(tǒng)任務(wù)仿真的過(guò)程

3.6,系統(tǒng)任務(wù)仿真

再回到我們的代碼,注釋掉了一些代碼吧,我們把那些代碼給加上,以其中一個(gè)過(guò)程為例

f8a31d26-c42c-11ec-bce3-dac502259ad0.jpg

假設(shè)讀回的指令碼位101,即LDA,如果我在fentch_8的高電平期間且在cpu輸出地址為奇數(shù)的時(shí)候記錄一下此時(shí)的時(shí)間、指令、地址、目的地址、數(shù)據(jù)的話(huà)就可以不用看波形,讓電腦來(lái)幫助我們來(lái)分析了,因此作如下處理

f8b1b2c8-c42c-11ec-bce3-dac502259ad0.jpg


這里我延時(shí)60ns,是因?yàn)榈谝淮斡涗浀臅r(shí)候數(shù)據(jù)總線(xiàn)上還沒(méi)有數(shù)據(jù),只有延時(shí)一會(huì)才會(huì)有數(shù)據(jù),即上面那張波形圖右邊那根黃色的線(xiàn)處記錄一下數(shù)據(jù),并將其顯示。我們也可以加上一下標(biāo)注,來(lái)幫助我們觀(guān)察

這樣我們?cè)賮?lái)仿真的時(shí)候就不用看波形了,直接打開(kāi)transcript一欄觀(guān)察記錄即可

f8be9452-c42c-11ec-bce3-dac502259ad0.jpg

這樣便可以為我們省下大量的仿真時(shí)間

04. 總結(jié)

這里提出以下幾點(diǎn)建議供大家參考:


? 封裝有用且常用的 testbench, testbench 中可以使用 task 或 function 對(duì)代碼進(jìn)行封裝, 下次利用時(shí)靈活調(diào)用即可;


? 如果待測(cè)試文件中存在雙向信號(hào)(inout)需要注意, 需要一個(gè) reg 變量來(lái)表示輸入, 一個(gè) wire 變量表示輸出;


? 單個(gè) initial 語(yǔ)句不要太復(fù)雜,可分開(kāi)寫(xiě)成多個(gè) initial 語(yǔ)句, 便于閱讀和修改;


? Testbench 說(shuō)到底是依賴(lài) PC 軟件平臺(tái), 必須與自身設(shè)計(jì)的硬件功能相搭配。

串行口通信電路設(shè)計(jì)

1、頂層模塊

寫(xiě)程序都一樣,不能多有的程序都寫(xiě)在一個(gè)模塊里,那樣看起來(lái)很麻煩,出了錯(cuò)誤也不好維護(hù),對(duì)于一些小的程序我們可以寫(xiě)在一個(gè)模塊里,但程序一旦復(fù)雜起來(lái)還是要懂得模塊化編程的,對(duì)于頂層模塊,最好是只寫(xiě)接口就好了,例如:


f8cb465c-c42c-11ec-bce3-dac502259ad0.jpg

這段代碼中,rx_232是我們的底層模塊名,后面跟著的那個(gè)rx呢是我們自己取的名字,是任意的。后面的一大串呢就是接口,為了直觀(guān)呢,建議大家采用我的這種寫(xiě)法,看上去比較清楚明白,括號(hào)里面的接口是我們頂層文件的接口,括號(hào)外面的是我們調(diào)用底層模塊的接口,這些接口要一一對(duì)應(yīng)正確才能保證數(shù)據(jù)之間的傳輸。

在頂層模塊中,我們只定義了數(shù)據(jù)輸入接口,用來(lái)接收數(shù)據(jù),數(shù)據(jù)輸出接口,用于發(fā)送數(shù)據(jù),時(shí)鐘接口,和復(fù)位接口。這四個(gè)接口是有輸入輸出關(guān)系的,對(duì)于其他的接口,是屬于我們整個(gè)模塊內(nèi)部的接口,是模塊與模塊之間的接口,既非輸入,也非輸出,相當(dāng)于一根導(dǎo)線(xiàn)一樣,所以我們把他們定義成wire型變量

f8da15ba-c42c-11ec-bce3-dac502259ad0.jpg

2、波特率選擇模塊


單片機(jī)或者計(jì)算機(jī)在串口通信時(shí)的傳輸速率用波特率表示,9600bps表示的就是每秒鐘傳送9600位的數(shù)據(jù),這里之所以計(jì)數(shù)到5027,在這里算一下。


1秒傳送9600位,那么傳送一位的時(shí)間就可以算出,即1s=1000_000_000ns,所以傳送一位數(shù)據(jù)需要1000_000_000/9600=
104166ns,而我們的時(shí)鐘周期為20ns,因此需要計(jì)數(shù)到104166/20=5028個(gè)時(shí)鐘周期

下面是串口通信時(shí)序圖


f8e75a9a-c42c-11ec-bce3-dac502259ad0.jpg

我再來(lái)解釋一下這個(gè)圖吧,我當(dāng)時(shí)學(xué)單片機(jī)的時(shí)候還真是沒(méi)怎么重視這張圖,只知道只要一個(gè)指令就可以發(fā)送,沒(méi)有真正搞清楚是怎么發(fā)送和接受的,那就在這里復(fù)習(xí)一下吧,計(jì)算機(jī)和單片機(jī)之間進(jìn)行通信,這里用的是rs232通信方式,即通信之前,計(jì)算機(jī)和單片機(jī)之前要設(shè)定好相同的波特率,只有波特率相同了才能進(jìn)行通信。

其次,計(jì)算機(jī)發(fā)送數(shù)據(jù)時(shí)要先發(fā)送一個(gè)起始位,一般是低電平,后面跟著的是8位數(shù)據(jù)位,奇偶校驗(yàn)位,停止位等,當(dāng)起始位低電平信號(hào)傳送到我們的接收端口時(shí),在接收模塊中會(huì)發(fā)送一個(gè)命令給波特率時(shí)鐘計(jì)數(shù)器,開(kāi)始計(jì)時(shí),計(jì)時(shí)到一半的時(shí)候會(huì)產(chǎn)生一個(gè)采樣高脈沖信號(hào),當(dāng)接收模塊檢測(cè)到這個(gè)高脈沖之后就會(huì)將數(shù)據(jù)存到寄存器中,當(dāng)檢測(cè)到第11個(gè)脈沖信號(hào)時(shí),也就是代表一幀的數(shù)據(jù)接收完畢,發(fā)送模塊就給波特率選擇模塊發(fā)送一個(gè)停止信號(hào)告訴它停止計(jì)時(shí)。

同時(shí),當(dāng)數(shù)據(jù)接收完畢之后也會(huì)產(chǎn)生一個(gè)信號(hào)告訴發(fā)送模塊,信號(hào)已經(jīng)接收完畢,準(zhǔn)備發(fā)送,這個(gè)時(shí)候發(fā)送模塊再給波特率計(jì)時(shí)模塊發(fā)送一個(gè)信號(hào)開(kāi)始計(jì)時(shí),計(jì)數(shù)到某一位的中間時(shí)產(chǎn)生一個(gè)采樣信號(hào),當(dāng)發(fā)送模塊檢測(cè)到采樣信號(hào)之后就將寄存器里的數(shù)據(jù)送到發(fā)送端,每次只送一位,這樣就實(shí)現(xiàn)了數(shù)據(jù)的接收與發(fā)送。

下面是波特率計(jì)時(shí)模塊的主要程序部分


f8f23352-c42c-11ec-bce3-dac502259ad0.jpg

3、數(shù)據(jù)接收模塊


在接收模塊中,為了準(zhǔn)確的檢測(cè)計(jì)算機(jī)發(fā)送來(lái)的數(shù)據(jù)起始位的那個(gè)低電平信號(hào),用到了邊沿脈沖檢測(cè)法,可以有效的避免毛刺現(xiàn)象帶來(lái)的問(wèn)題


f8fcd3ca-c42c-11ec-bce3-dac502259ad0.jpg

下面是發(fā)送部分的主要程序段

f9094204-c42c-11ec-bce3-dac502259ad0.jpg

4、數(shù)據(jù)發(fā)送模塊


發(fā)送模塊原理上和接受模塊是一樣的,不同點(diǎn)就是接收模塊通過(guò)邊沿檢測(cè)法檢測(cè)起始位低電平信號(hào)來(lái)啟動(dòng)接收數(shù)據(jù),而發(fā)送模塊是通過(guò)檢測(cè)數(shù)據(jù)發(fā)送完畢后,我們認(rèn)為得置一個(gè)低電平信號(hào),發(fā)送模塊通過(guò)檢測(cè)這個(gè)低電平信號(hào)來(lái)啟動(dòng)發(fā)送。見(jiàn)下圖

f916e6ca-c42c-11ec-bce3-dac502259ad0.jpg

下面是生成的RTL視圖

f926529a-c42c-11ec-bce3-dac502259ad0.jpg

下面是測(cè)試結(jié)果

f9319d94-c42c-11ec-bce3-dac502259ad0.jpg

手把手解析時(shí)序邏輯乘法器代碼

下面是一段16位乘法器的代碼,大家可以先瀏覽一下,之后我再做詳細(xì)解釋

module mux16(clk,rst_n,start,ain,bin,yout,done);input clk; //芯片的時(shí)鐘信號(hào)。input rst_n; //低電平復(fù)位、清零信號(hào)。定義為0表示芯片復(fù)位;定義為1表示復(fù)位信號(hào)無(wú)效。input start; //芯片使能信號(hào)。定義為0表示信號(hào)無(wú)效;定義為1表示芯片讀入輸入管腳得乘數(shù)和被乘數(shù),并將乘積復(fù)位清零。input[15:0] ain; //輸入a(被乘數(shù)),其數(shù)據(jù)位寬為16bit.input[15:0] bin; //輸入b(乘數(shù)),其數(shù)據(jù)位寬為16bit.output[31:0] yout; //乘積輸出,其數(shù)據(jù)位寬為32bit.output done; //芯片輸出標(biāo)志信號(hào)。定義為1表示乘法運(yùn)算完成.reg[15:0] areg; //乘數(shù)a寄存器reg[15:0] breg; //乘數(shù)b寄存器reg[31:0] yout_r; //乘積寄存器reg done_r;reg[4:0] i; //移位次數(shù)寄存器//------------------------------------------------//數(shù)據(jù)位控制always @(posedge clk or negedge rst_n)if(!rst_n) i <= 5'd0;else if(start && i < 5'd17) i <= i+1'b1;else if(!start) i <= 5'd0;//------------------------------------------------//乘法運(yùn)算完成標(biāo)志信號(hào)產(chǎn)生always @(posedge clk or negedge rst_n)if(!rst_n) done_r <= 1'b0;else if(i == 5'd16) done_r <= 1'b1; //乘法運(yùn)算完成標(biāo)志else if(i == 5'd17) done_r <= 1'b0; //標(biāo)志位撤銷(xiāo)assign done = done_r;//------------------------------------------------//專(zhuān)用寄存器進(jìn)行移位累加運(yùn)算always @(posedge clk or negedge rst_n) beginif(!rst_n) beginareg <= 16'h0000;breg <= 16'h0000;yout_r <= 32'h00000000;endelse if(start) begin //啟動(dòng)運(yùn)算if(i == 5'd0) begin //鎖存乘數(shù)、被乘數(shù)areg <= ain;breg <= bin;endelse if(i > 5'd0 && i < 5'd16) beginif(areg[i-1]) yout_r = {1'b0,yout[30:15]+breg,yout_r[14:1]}; //累加并移位else yout_r <= yout_r>>1; //移位不累加endelse if(i == 5'd16 && areg[15]) yout_r[31:16] <= yout_r[31:16]+breg; //累加不移位endendassign?yout?=?yout_r;endmodule

要理解這段代碼,首先要弄明白幾個(gè)點(diǎn)。

1、我們通常寫(xiě)的十進(jìn)制的乘法豎式,同樣適用于二進(jìn)制。下面我們就以這個(gè)算式為例:1011 x 0111 =0100_1101。

2、兩個(gè)16位的數(shù)相乘,結(jié)果是32位的,沒(méi)有32位要在高位補(bǔ)零。

3、計(jì)算兩個(gè)16位的數(shù)相乘需要移位15次。

例如:


1 0 1 1

x 0 1 1 1

------------------------------------

1 0 1 1

1 0 1 1

1 0 1 1

0 0 0 0

------------------------------------

1 0 0 1 1 0 1


前三次計(jì)算是移位的,最后一次沒(méi)有移位

4、兩個(gè)16位的數(shù)相加,結(jié)果是17位的,不夠17位最高位補(bǔ)零。

例如語(yǔ)句yout[30:15]+breg,結(jié)果是17位的。


知道了這些,我們就開(kāi)始看代碼了

1)、接口部分注釋寫(xiě)的很清楚,這里就不提了

2)、數(shù)據(jù)位控制部分

always @(posedge clk or negedge rst_n)if(!rst_n) i <= 5'd0;else if(start && i < 5'd17) i <= i+1'b1;else if(!start) i <= 5'd0;


當(dāng)start為1時(shí),芯片讀入兩個(gè)數(shù),此時(shí)開(kāi)始計(jì)數(shù),計(jì)數(shù)16次,乘法運(yùn)算開(kāi)始

3)、乘法運(yùn)算完成標(biāo)志信號(hào)產(chǎn)生

always @(posedge clk or negedge rst_n)if(!rst_n) done_r <= 1'b0;else if(i == 5'd16) done_r <= 1'b1; //乘法運(yùn)算完成標(biāo)志else if(i == 5'd17) done_r <= 1'b0; //標(biāo)志位撤銷(xiāo)assign done = done_r;


這部分也很好理解

4)、專(zhuān)用寄存器進(jìn)行移位累加運(yùn)算


這里為了簡(jiǎn)單,就用15到18位代替15到30位

f93e9dd2-c42c-11ec-bce3-dac502259ad0.png

f951c7fe-c42c-11ec-bce3-dac502259ad0.png

f95f784a-c42c-11ec-bce3-dac502259ad0.png

以上部分是最主要的計(jì)算部分,其他地方相對(duì)來(lái)說(shuō)還比較簡(jiǎn)單,例如當(dāng)乘數(shù)某一位為0時(shí),不用累加,直接右移,當(dāng)i計(jì)數(shù)到16時(shí),此時(shí)就不用再移位了,可以直接用位數(shù)表示,直接累加即可。

下面是仿真圖

f9703b4e-c42c-11ec-bce3-dac502259ad0.png

基于FIFO的串口發(fā)送機(jī)設(shè)計(jì)全流程

首先來(lái)解釋一下FIFO的含義,F(xiàn)IFO就是First Input First Output的縮寫(xiě),就是先入先出的意思,按照我的理解就是,先進(jìn)去的數(shù)據(jù)先出,例如一個(gè)數(shù)組的高位先進(jìn),那么讀出來(lái)的時(shí)候也就高位先出。下面是百度百科的解釋。

FIFO一般用于不同時(shí)鐘域之間的數(shù)據(jù)傳輸,比如FIFO的一端是AD數(shù)據(jù)采集,另一端是計(jì)算機(jī)的PCI總線(xiàn),假設(shè)其AD采集的速率為16位 100K SPS,那么每秒的數(shù)據(jù)量為100K×16bit=1.6Mbps,而PCI總線(xiàn)的速度為33MHz,總線(xiàn)寬度32bit,其最大傳輸速率為1056Mbps,在兩個(gè)不同的時(shí)鐘域間就可以采用FIFO來(lái)作為數(shù)據(jù)緩沖。另外對(duì)于不同寬度的數(shù)據(jù)接口也可以用FIFO,例如單片機(jī)為8位數(shù)據(jù)輸出,而DSP可能是16位數(shù)據(jù)輸入,在單片機(jī)與DSP連接時(shí)就可以使用FIFO來(lái)達(dá)到數(shù)據(jù)匹配的目的。

f97d1bac-c42c-11ec-bce3-dac502259ad0.png

我們將這三個(gè)模塊分別定義為dataoutput塊,fifo_ctrl塊和uart_ctrl塊。現(xiàn)在考慮連線(xiàn),具體到每一根連線(xiàn),這樣根據(jù)圖來(lái)寫(xiě)代碼要比直接用腦子構(gòu)圖要方便的多。三個(gè)模塊,先考慮時(shí)鐘和復(fù)位信號(hào)線(xiàn),三個(gè)模塊都有,然后,數(shù)據(jù)產(chǎn)生模塊要將產(chǎn)生的數(shù)據(jù)發(fā)給FIFO模塊,所以要有數(shù)據(jù)寫(xiě)入線(xiàn),我們定義它為wr-datain,數(shù)據(jù)寫(xiě)入FIFO塊后總要輸出,這些數(shù)據(jù)就是我們要發(fā)送的數(shù)據(jù),所以定義輸出數(shù)據(jù)線(xiàn)tx_data,先不管FIFO,我們?cè)賮?lái)定義數(shù)據(jù)發(fā)送模塊的連線(xiàn),數(shù)據(jù)發(fā)送總要有個(gè)啟動(dòng)信號(hào),所以我們定義變量tx_start,之后,還要有一個(gè)輸出端給PC機(jī),我們定義這個(gè)輸出端位rs232。

對(duì)于FIFO模塊的例化過(guò)程很簡(jiǎn)單就不做過(guò)多的說(shuō)明,只把接口說(shuō)一下,F(xiàn)IFO模塊除了時(shí)鐘,復(fù)位信號(hào)外,還有數(shù)據(jù)輸入端口,這個(gè)端口要和之前的數(shù)據(jù)產(chǎn)生模塊的數(shù)據(jù)輸出端口相連,還有寫(xiě)請(qǐng)求端口,高電平有效,數(shù)據(jù)發(fā)送模塊每隔1秒鐘產(chǎn)生一個(gè)16位的數(shù)據(jù),并發(fā)送寫(xiě)請(qǐng)求命令給FIFO,還有讀請(qǐng)求命令,高電平有效數(shù)據(jù)發(fā)送模塊在發(fā)送數(shù)據(jù)時(shí)要發(fā)送一個(gè)讀請(qǐng)求給FIFO,從中讀取數(shù)據(jù)后再發(fā)送給PC機(jī),還有空信號(hào)empty,只要檢測(cè)到FIFO中有數(shù)據(jù),empty就為低電平,我們可用這個(gè)信號(hào)來(lái)啟動(dòng)數(shù)據(jù)發(fā)送模塊。這樣一來(lái),我們的整體框架就出來(lái)了有了這個(gè)整體框架,再寫(xiě)代碼就容易多了。

下面是RTL視圖

f98ad602-c42c-11ec-bce3-dac502259ad0.jpg

按照這個(gè)框架,先把接口定義出來(lái),中間的連線(xiàn)用wire型

f997385c-c42c-11ec-bce3-dac502259ad0.jpg

設(shè)計(jì)完端口之后我們就來(lái)設(shè)計(jì)底層模塊,先設(shè)計(jì)數(shù)據(jù)產(chǎn)生模塊dataoutput,這個(gè)部分主要是產(chǎn)生數(shù)據(jù),可用一個(gè)分頻電路實(shí)現(xiàn)每1s發(fā)送一次的數(shù)據(jù),產(chǎn)生這16位數(shù)據(jù)的時(shí)候,需要16個(gè)時(shí)鐘,每個(gè)時(shí)鐘數(shù)據(jù)自加1,總體來(lái)說(shuō)比較簡(jiǎn)單

f9a70264-c42c-11ec-bce3-dac502259ad0.jpg

寫(xiě)完一個(gè)模塊之后養(yǎng)成好習(xí)慣,馬上把端口例化

f9b4befe-c42c-11ec-bce3-dac502259ad0.jpg

數(shù)據(jù)產(chǎn)生以后就要進(jìn)入緩沖器FIFO,由于這段代碼我們是調(diào)用的,所以只要例化接口就好了,只需要將產(chǎn)生的fifo_ctrl_inst文件中例化好的代碼拷貝粘貼就好

f9c10b64-c42c-11ec-bce3-dac502259ad0.jpg

最后我們要寫(xiě)數(shù)據(jù)發(fā)送部分,之前已經(jīng)講過(guò),數(shù)據(jù)發(fā)送部分還要包括兩個(gè)子模塊,一個(gè)是波特率匹配模塊,一個(gè)是發(fā)送模塊,既然又包括兩個(gè)子模塊,那么我們還要構(gòu)建一個(gè)框圖

按照之前的例子,當(dāng)FIFO當(dāng)中有數(shù)據(jù)時(shí)empty就會(huì)拉低,我們把它取反后送給發(fā)送模塊,告訴發(fā)送模塊準(zhǔn)備發(fā)送,這樣,發(fā)送模塊就會(huì)產(chǎn)生一個(gè)波特率計(jì)數(shù)器啟動(dòng)信號(hào)bps_start給波特率匹配模塊,波特率匹配模塊收到信號(hào)后立馬開(kāi)始匹配計(jì)數(shù),并產(chǎn)生采集信號(hào),將采集信號(hào)傳給發(fā)送模塊,發(fā)送模塊根據(jù)采集信號(hào),將數(shù)據(jù)一位一位發(fā)送出去。知道了這個(gè)原理之后,我們構(gòu)建起這樣一個(gè)框架

f9cd5946-c42c-11ec-bce3-dac502259ad0.jpg

根據(jù)這個(gè)框圖,我們定義端口和線(xiàn)

f9da844a-c42c-11ec-bce3-dac502259ad0.jpg

定義完端口之后,開(kāi)始寫(xiě)發(fā)送模塊,用邊沿脈沖檢測(cè)法檢測(cè)啟動(dòng)信號(hào)tx_start信號(hào)的上升沿來(lái)啟動(dòng)發(fā)送部分,波特率配置模塊具體代碼在前面也文章中有給出,就不在說(shuō)明,寫(xiě)完之后例化端口,這兩個(gè)模塊作為數(shù)據(jù)發(fā)送模塊的子模塊,要在數(shù)據(jù)發(fā)送模塊下例化

f9e95010-c42c-11ec-bce3-dac502259ad0.jpg

f9f5f5b8-c42c-11ec-bce3-dac502259ad0.jpg

這樣一來(lái),我們整個(gè)設(shè)計(jì)就完成了,看上去很簡(jiǎn)單,但是從我自己實(shí)踐的角度來(lái)說(shuō)還是有點(diǎn)挑戰(zhàn)的,包括中間出現(xiàn)的各種問(wèn)題,下面就來(lái)分享一下我在做這個(gè)設(shè)計(jì)時(shí)遇到的問(wèn)題

1.例化問(wèn)題
在例化端口時(shí),要注意括號(hào)里面的才是本層模塊的端口,也就是說(shuō)在本層模塊上面已經(jīng)定義過(guò)的變量,括號(hào)外面的才是被調(diào)用模塊的端口,也在下層模塊的頂部被聲明,我在寫(xiě)這段程序的時(shí)候?qū)⒍哳嵉沽?,?dǎo)致連線(xiàn)不成功,最終是通過(guò)查看RTL視圖知道了哪根線(xiàn)有問(wèn)題才修改成功的


fa0322f6-c42c-11ec-bce3-dac502259ad0.jpg

2.同一個(gè)變量不能在多個(gè)always語(yǔ)句中被賦值
我們可能習(xí)慣這么寫(xiě)

always @ (posedge clk ornegedge rst_n)if(!rst_n) num <= 1'b0;else num <= num+1'b1;


那么,num的值在其他always語(yǔ)句中就不允許再被賦值或者清零,我在寫(xiě)的時(shí)候在其他always語(yǔ)句中將num 清零了,導(dǎo)致編譯不成功

3.定義變量之前不要出現(xiàn)該變量,即使后面又定義了
例如,我先進(jìn)行num的運(yùn)算,之后再定義num,reg [3:0] num,這樣寫(xiě)的話(huà)雖然編譯沒(méi)有錯(cuò)誤,但是在調(diào)用modelsim仿真的時(shí)候它會(huì)出現(xiàn)編譯錯(cuò)誤,所以為了規(guī)范,不要這樣寫(xiě)

4. 在邊沿脈沖檢測(cè)的時(shí)候,習(xí)慣于檢測(cè)下降沿,而這里是檢測(cè)tx_en 的上升沿,所以我在復(fù)位清零的時(shí)候錯(cuò)誤的將兩級(jí)寄存器賦值為0,實(shí)際上在檢測(cè)上升沿時(shí)要對(duì)兩級(jí)寄存器復(fù)位時(shí)置一,再把最后一級(jí)寄存器取反后與上一級(jí)相與。

fa0f71c8-c42c-11ec-bce3-dac502259ad0.jpg

5.在發(fā)送數(shù)據(jù)部分,由于受到上次寫(xiě)接收部分程序的影響,沒(méi)有將起始位發(fā)送出去,因?yàn)樵诮邮詹糠郑遣恍枰邮掌鹗嘉坏?,是從第一位開(kāi)始,而在發(fā)送部分只有先發(fā)送起始位才能和上位機(jī)握手通信,還有在發(fā)送完數(shù)據(jù)后要發(fā)送停止位,其他情況下都發(fā)送高電平來(lái)阻止通信的進(jìn)行

fa1ce95c-c42c-11ec-bce3-dac502259ad0.jpg

6.最后一個(gè)問(wèn)題是最棘手的問(wèn)題,我找了好大一半天也沒(méi)發(fā)現(xiàn),最后還是根據(jù)源代碼找出來(lái)的,不過(guò)我還是不知道將這兩條語(yǔ)句顛倒了對(duì)程序有什么影響,只知道顛倒后數(shù)據(jù)會(huì)一直在發(fā)送,不會(huì)像預(yù)設(shè)一樣,每隔一秒發(fā)送一次,至今還是搞不清楚,希望大神指點(diǎn)迷津

fa29d342-c42c-11ec-bce3-dac502259ad0.jpg

總結(jié)

語(yǔ)法上的錯(cuò)誤到不至于太難,寫(xiě)的多了就不會(huì)出錯(cuò)了,關(guān)鍵是邏輯上的錯(cuò)誤很隱蔽,也很難發(fā)現(xiàn),可以通過(guò)RTL視圖來(lái)檢測(cè)連線(xiàn)上是否正確,還可以借助仿真工具。

審核編輯 :李倩


聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀(guān)點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • FPGA
    +關(guān)注

    關(guān)注

    1625

    文章

    21636

    瀏覽量

    601315
  • 寄存器
    +關(guān)注

    關(guān)注

    31

    文章

    5301

    瀏覽量

    119862

原文標(biāo)題:工程師深度:FPGA 高手養(yǎng)成記

文章出處:【微信號(hào):zhuyandz,微信公眾號(hào):FPGA之家】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    FIFO Generator的Xilinx官方手冊(cè)

    FIFO作為FPGA崗位求職過(guò)程中最常被問(wèn)到的基礎(chǔ)知識(shí)點(diǎn),也是項(xiàng)目中最常被使用到的IP,其意義是非常重要的。本文基于對(duì)FIFO Generator的Xilinx官方手冊(cè)的閱讀與總結(jié),匯總主要知識(shí)點(diǎn)
    的頭像 發(fā)表于 11-12 10:46 ?75次閱讀
    <b class='flag-5'>FIFO</b> Generator的Xilinx官方手冊(cè)

    皮帶輸送機(jī)監(jiān)測(cè)預(yù)警物聯(lián)網(wǎng)系統(tǒng)

    皮帶輸送機(jī)是形成高效生產(chǎn)節(jié)奏的自動(dòng)化作業(yè)線(xiàn)的物料物流輸送設(shè)備,在家電、電子、電器、機(jī)械、煙草、注塑、郵電、印刷、食品等各行各業(yè)得到廣泛使用。隨著流程化生產(chǎn)的越來(lái)越專(zhuān)業(yè)與高效,任何導(dǎo)致生產(chǎn)停工的因素都
    的頭像 發(fā)表于 10-15 15:45 ?154次閱讀
    皮帶輸<b class='flag-5'>送機(jī)</b>監(jiān)測(cè)預(yù)警物聯(lián)網(wǎng)系統(tǒng)

    迪文串口屏ModBus開(kāi)發(fā)流程

    這里接前一章節(jié),繼續(xù)迪文屏的開(kāi)發(fā),前章主要講解基礎(chǔ)開(kāi)發(fā)流程,此章節(jié)開(kāi)始講解迪文ModBus協(xié)議棧的使用方法。前文指路:《迪文串口屏基礎(chǔ)GUI開(kāi)發(fā)流程》協(xié)議棧獲取,首先在迪文官方論壇上獲取
    的頭像 發(fā)表于 07-19 08:21 ?414次閱讀
    迪文<b class='flag-5'>串口</b>屏ModBus開(kāi)發(fā)<b class='flag-5'>流程</b>

    STC32和STC8H驅(qū)動(dòng)DS18B20測(cè)溫串口發(fā)送數(shù)據(jù)

    STC32G12K128 和 STC8H8K64U 驅(qū)動(dòng) DS18B20 模塊,采集環(huán)境溫度并通過(guò)串口發(fā)送數(shù)據(jù)至電腦
    的頭像 發(fā)表于 06-27 16:27 ?705次閱讀
    STC32和STC8H驅(qū)動(dòng)DS18B20測(cè)溫<b class='flag-5'>串口</b><b class='flag-5'>發(fā)送</b>數(shù)據(jù)

    同步FIFO和異步FIFO區(qū)別介紹

    ,并且間隔時(shí)間長(zhǎng),也就是突發(fā)寫(xiě)入。那么通過(guò)設(shè)置一定深度的FIFO,可以起到數(shù)據(jù)暫存的功能,且使得后續(xù)處理流程平滑。 時(shí)鐘域的隔離:主要用異步FIFO。對(duì)于不同時(shí)鐘域的數(shù)據(jù)傳輸,可以通過(guò)FIFO
    的頭像 發(fā)表于 06-04 14:27 ?1222次閱讀
    同步<b class='flag-5'>FIFO</b>和異步<b class='flag-5'>FIFO</b>區(qū)別介紹

    做STM32f103 USB雙緩存的時(shí)候,發(fā)送4K數(shù)據(jù)里面前64字節(jié)是0,為什么?

    做STM32f103 USB 雙緩存的時(shí)候, 采取ENP3的TXaddr1和TXaddr0的雙緩存ping-pong發(fā)送機(jī)制,每次上位機(jī)接收完4K數(shù)據(jù), 4K數(shù)據(jù)前64個(gè)字節(jié)全部是0,后面才是上位
    發(fā)表于 04-28 07:07

    STM32H753的FDCAN發(fā)送總是the Tx FIFO/Queue is full,為什么?

    FDCAN1_Handler.Init.TxFifoQueueElmtsNbr = 0;//發(fā)送 FIFO 序列元素編號(hào) FDCAN1_Handler.Init.TxFifoQueueMode
    發(fā)表于 03-28 06:32

    UART串口通信協(xié)議是什么?

    ,廣泛應(yīng)用于嵌入式領(lǐng)域。 在UART串口通信協(xié)議中,數(shù)據(jù)以字節(jié)的形式進(jìn)行傳輸。發(fā)送和接收端的通信流程如下: 1、通信波特率設(shè)置:發(fā)送端和接收端需要
    的頭像 發(fā)表于 03-19 17:26 ?1201次閱讀

    如何用DMA的方式讀寫(xiě)串口數(shù)據(jù)?

    串口接收(或者發(fā)送)的數(shù)據(jù)比較大,如果用中斷逐字節(jié)從FIFO讀數(shù)據(jù)太耗時(shí)了,光盤(pán)里的找不到有關(guān)DMA讀寫(xiě)串口的demo
    發(fā)表于 01-17 07:35

    dma和串口直接發(fā)送的區(qū)別

    DMA(Direct Memory Access)和串口直接發(fā)送是兩種不同的數(shù)據(jù)傳輸方式,它們?cè)趯?shí)現(xiàn)上有著明顯的區(qū)別和優(yōu)劣勢(shì)。本文將詳細(xì)介紹DMA和串口直接發(fā)送的原理、優(yōu)缺點(diǎn)以及適用場(chǎng)
    的頭像 發(fā)表于 01-07 17:43 ?2609次閱讀

    USB虛擬串口串口1可以同時(shí)發(fā)送

    可以同時(shí)發(fā)送,USB虛擬串口和物理串口1都可以作為數(shù)據(jù)傳輸?shù)耐ǖ溃梢酝瑫r(shí)操作和發(fā)送數(shù)據(jù)。 USB虛擬串口是一種通過(guò)USB接口模擬的
    的頭像 發(fā)表于 01-04 11:26 ?1450次閱讀

    簡(jiǎn)單認(rèn)識(shí)微波器件

    微波器件 (Microwave Devices)是指工作在微波波段 (300MHz ~ 300GHz)的器件,常應(yīng)用在信號(hào)發(fā)送機(jī)、信號(hào)接收機(jī)、雷達(dá)系統(tǒng)、手機(jī)移動(dòng)通信系統(tǒng)等電子產(chǎn)品中。微波器件包括微波真空器件、微波半導(dǎo)體器件等,由于后者的可集成性,本詞條主要描述后者。?
    的頭像 發(fā)表于 01-03 09:52 ?1165次閱讀

    單片機(jī)串口通信的接收與發(fā)送

    的原理。串口通信是通過(guò)發(fā)送和接收兩根線(xiàn)來(lái)實(shí)現(xiàn)的,分別為發(fā)送線(xiàn)(Tx)和接收線(xiàn)(Rx)。當(dāng)單片機(jī)發(fā)送數(shù)據(jù)時(shí),數(shù)據(jù)通過(guò)發(fā)送線(xiàn)
    的頭像 發(fā)表于 12-20 14:03 ?3415次閱讀

    單片機(jī)串口通信的接收與發(fā)送程序

    單片機(jī)串口通信的接收與發(fā)送程序 一、引言 單片機(jī)串口通信是一種常見(jiàn)的通信方式,廣泛應(yīng)用于各種嵌入式系統(tǒng)和工業(yè)控制領(lǐng)域。通過(guò)串口通信,單片機(jī)可以與其他設(shè)備或計(jì)算機(jī)進(jìn)行數(shù)據(jù)交換,實(shí)現(xiàn)遠(yuǎn)程監(jiān)
    的頭像 發(fā)表于 12-19 13:57 ?5514次閱讀

    EDA流程的重要意義,以及國(guó)內(nèi)EDA流程進(jìn)展

    的方式。如果一款工具能夠覆蓋特定芯片在上述流程中的設(shè)計(jì)任務(wù),那么我們就將其稱(chēng)之為流程EDA工具,或者是流程EDA平臺(tái)。 在國(guó)產(chǎn)EDA發(fā)展
    的頭像 發(fā)表于 12-14 00:08 ?2219次閱讀