verilog基礎語法之數據類型

verilog基礎語法之數據類型

    • 1、 wire類型
    • 2、 reg類型
    • 3、向量

? ?Verilog最常用的數據類型有兩種:線網(wire)和寄存器(reg)。其中,wire 類型表示硬件單元之間的物理連線,reg用來表示存儲單元。

1、 wire類型

? ?wire類型是信號在不同元器件之間傳遞的媒介,用于表示硬件電路單元之間的物理連線,由其連接的器件的輸出端連續驅動。如果沒有驅動元件連接到wire型變量,或者存在沖突的驅動(即多個驅動源同時驅動同一個wire),那么該變量的值默認為"High-Impedance"(高阻態),通常表示為"Z"。高阻態是一種不驅動信號的狀態,相當于該信號線上沒有電流流動。“驅動”是指信號源對連線施加的電平,這個信號源可以是一個邏輯門、觸發器、緩沖器、驅動元件或者任何其他可以產生信號的硬件實體。
? ?另外,wire型變量的值可以由連續賦值(使用=操作符)或非阻塞賦值(在always塊中使用<=操作符)決定。連續賦值類似于組合邏輯,它描述了輸入變量和輸出變量之間的直接關系,而輸出值會隨著輸入值的變化而立即變化。
示例:

wire signal_wire; // 聲明一個wire類型的信號線
assign signal_wire = some_driver; // some_driver是一個驅動源,可以是門、觸發器等

在這個例子中,assign語句定義了一個連續賦值,some_driver是驅動signal_wire的驅動源。如果some_driver是一個邏輯門的輸出,那么signal_wire將根據該邏輯門的輸入而變化。

wire gnd = 1'b0;//創建一個名為 gnd 的全局地線信號,它被賦予了一個邏輯0(二進制值0)的初始值,地線通常在電路中表示參考點或0電平。

這行代碼定義了一個名為 gnd 的 wire 類型的信號,并初始化為邏輯值 0。在某些情況下,設計者可能會使用 wire 類型來定義一個常量,即使用 wire 來表示一個始終為特定值的信號,但更常見的做法是使用 parameter 或 localparam 關鍵字來定義常量。對于地線,一般不需要在代碼中顯式定義,因為地線通常在FPGA的物理設計中是預定義的,并在布局時連接到相應的電源和地引腳。

? ?需要特別說明的是,wire型變量通常用于表示模塊的端口或者作為信號的傳遞媒介。它們不應當在always塊內部被賦值,因為wire代表著連線,其值由外部信號源決定,而非由always塊內的邏輯產生。如果試圖在always塊中對wire型變量使用<=操作符,這將導致編譯錯誤,因為wire不允許在always塊內部賦值。 然而,wire型變量可以在always塊中被用作非阻塞賦值表達式中的一個源(source),但這只出現在一個模塊的輸出端口被另一個模塊的輸入端口所驅動的情況下。在這種情況下,wire實際上是連接兩個模塊的信號線。

? ?以下是一個簡單的示例,演示了如何在模塊間使用wire型變量進行非阻塞賦值:

module d_flip_flop(input wire clk,       // 時鐘信號input wire data_in,   // 數據輸入output reg data_out  // 數據輸出
);`在這里插入代碼片`// 使用非阻塞賦值在時鐘上升沿捕獲data_in的值
always @(posedge clk) begindata_out <= data_in;endendmodule// 測試模塊,實例化d_flip_flop
module testbench();wire clk;wire data_in;wire data_out;// 實例化d_flip_flop模塊d_flip_flop u_d_flip_flop(.clk(clk),.data_in(data_in),.data_out(data_out));// 驅動測試信號initial beginclk = 0;forever #10 clk = ~clk; // 產生時鐘信號endinitial begindata_in = 0;#20 data_in = 1; // 在時間20ns處改變輸入數據#20 data_in = 0;end// 監視輸出變化initial begin$monitor("Time = %t, clk = %b, data_in = %b, data_out = %b", $time, clk, data_in, data_out);endendmodule

在這個例子中,data_out是一個reg型變量,它在d_flip_flop模塊的always塊中使用非阻塞賦值從data_in獲得值。clk和data_in是wire型變量,它們在測試模塊testbench中被驅動,并且連接到d_flip_flop模塊的相應端口。請注意,盡管data_out是reg類型并且可以使用非阻塞賦值,但data_in和clk作為wire類型,它們的值是由測試模塊生成的信號所驅動的,而不是在d_flip_flop模塊內部的always塊中賦值。在這個示例的always塊中,data_in的值在時鐘邊沿被采樣,并在data_out中保持,直到下一個時鐘邊沿到來。

總結來說,在Verilog中,“驅動”指的是信號源對連線施加的電平,而驅動源是產生這些信號的任何硬件元件。如果沒有驅動源,wire型變量將呈現高阻態"Z"。

2、 reg類型

? ?reg用來表示存儲單元,它是一種可以存儲數據并保持其狀態的硬件元素。在仿真環境中,reg類型的變量行為與實際硬件中的寄存器類似,用于模擬寄存器的行為。在硬件實現中,reg聲明的變量將被映射到FPGA或ASIC中的相應寄存器結構。與wire不同,reg不是用于連接模塊的物理線,而是用于表示可以存儲狀態的寄存器。以下是reg類型的一些關鍵特性和用法:

  • 狀態保持:reg類型的變量可以保持它們的值,直到它們被新的賦值語句更新。這種特性使得reg類型非常適合用于建模需要記憶先前值的硬件寄存器和觸發器。

  • 非阻塞賦值:reg類型的變量通常與非阻塞賦值(使用 <=操作符)一起使用,這在時序邏輯中非常重要。非阻塞賦值確保了多個寄存器可以在同一時鐘邊沿更新,而不會產生競態條件。

  • 時序控制:在always塊中,當指定了時鐘信號(例如 posedge clk 或 negedgeclk),reg變量的賦值將與時鐘信號的邊沿同步。

  • 初始化:可以在聲明時初始化reg變量,但這種初始化僅在仿真開始時有效,實際硬件實現中寄存器的初始狀態取決于其物理實現或配置過程。

  • 并發與順序:reg變量可以用于順序邏輯(在always塊中)和并發邏輯(在連續賦值語句之外聲明)。

示例一:使用<=操作符在always塊中對reg型變量賦值的示例:

module flip_flop(input wire clk,       // 時鐘信號input wire reset,     // 復位信號input wire data_in,   // 數據輸入output reg data_out  // 數據輸出
);// 觸發器行為的always塊
always @(posedge clk or posedge reset) beginif (reset) begin// 異步復位:當reset為高時,data_out被清零data_out <= 1'b0;end else begin// 時鐘邊沿觸發的數據鎖存:data_out在每個clk的上升沿捕獲data_in的值data_out <= data_in;end
endendmodule

在這個例子中,data_out是一個reg型變量,它在always塊中使用<=操作符進行賦值。當reset信號為高時,data_out被清零;否則,在clk的每個上升沿,data_out將捕獲data_in的值。

示例二:使用reg變量進行并發邏輯賦值的示例:

module combinatorial_logic(input wire [3:0] a,input wire [3:0] b,output reg [3:0] c
);// 并發賦值:輸出端口c的值由輸入a和b的當前值決定
// 這個always塊沒有時鐘信號,因此它在仿真期間是并發執行的
always @(a or b) beginc = a + b;
endendmodule

在這個例子中,模塊combinatorial_logic有一個4位寬的輸入a和b,以及一個8位寬的輸出c。輸出c被聲明為reg類型,并且它的值是由輸入a和b的當前值決定的。這里的reg變量可以用于并發賦值,當reg變量在連續賦值語句之外聲明,并且賦值不是發生在時鐘邊沿的always塊中時,它們可以用于描述并發邏輯。這種用法通常在描述組合邏輯時看到,其中reg變量的賦值不是基于時序信號,而是基于其他信號的變化。盡管,使用了always塊,但由于缺少時鐘信號或復位信號,這個always塊實際上定義了并發邏輯。當仿真環境中a或b的值發生變化時,c的值會立即更新,這與連續賦值的行為類似。

? ?請注意,這種使用reg進行并發賦值的方式并不常見,因為它可能會隱藏邏輯的時序特性,使得設計難以驗證和理解。在實際的硬件設計中,我們通常使用assign語句來創建組合邏輯的連續賦值,而使用帶有時鐘信號的always塊來創建順序邏輯。

? ?此外,當設計被綜合到實際的硬件時,沒有時鐘信號的always塊可能會被優化掉,因為綜合工具會認為這是一個恒定的賦值,而不是一個需要時序控制的寄存器賦值。在大多數情況下,如果你發現自己需要使用reg來創建并發邏輯,你應該重新考慮設計,并可能使用assign語句來代替。

3、向量

? ?在Verilog中,向量數據類型是一種復合數據類型,是Verilog中用于表示多位寬信號的一種數據結構,它允許你將多個數據位組合成一個單一的實體。Verilog中的向量可以是單比特的集合,也可以是多位的集合,它們在硬件描述中非常有用,因為它們可以表示多比特的信號、總線或寄存器、內存等。向量的索引是從高位到低位遞減的,即[7:0]表示從位7(最高位)到位0(最低位)。這種索引方式與常見的十進制計數方式相反,需要特別注意以避免混淆。向量在Verilog中非常有用,因為它們允許對多位寬的信號進行統一的操作和管理。以下是Verilog中向量數據類型的一些關鍵點:

  • 位寬(Bit-width):向量數據類型具有明確的位寬,定義了向量中包含的位數。位寬在聲明時指定,使用方括號[]表示。

  • 線網(Wires):wire類型的向量是最常用的,用于表示多個位的連接,如數據總線或地址總線。

  • 寄存器(Registers):reg類型的向量用于表示需要存儲的多位信號,通常在時序邏輯中使用。

  • 索引(Indexing):向量可以被索引,允許訪問向量中的單個位或位的子集。索引從0開始,到位寬減一結束。

  • 部分選擇(Part Selection):可以基于起始位和結束位選擇向量的一部分,用于創建子向量。

  • 拼接(Concatenation):可以使用{a, b}的語法將兩個或多個向量拼接成一個新的向量。

  • 重復(Repetition):可以使用大括號和數字的組合,如{n{element}},來創建一個包含n個重復元素的向量。

  • 位選擇和部分選擇操作符:位選擇:使用方括號加索引,如vector[3]選擇向量vector的第4位(索引從0開始)。部分選擇:使用方括號加索引范圍,如vector[3:1]選擇從第4位到第2位的子向量。

  • 向量賦值:可以對整個向量進行賦值,也可以對向量的一部分進行賦值。

另外,以下是聲明向量的兩種基本方式:

  • 使用方括號:在聲明時,使用方括號[]來指定位寬,其中包含兩位數字,分別表示向量的高(MSB)和低(LSB)位索引。
  • 單比特聲明:如果向量的所有位都是單獨聲明的,然后通過拼接(concatenation)操作符{}來組合成一個向量。

以下是一些使用向量的示例:

module vector_example(input wire [7:0] data_in, // 8位寬的輸入向量output reg [15:0] data_out, // 16位寬的輸出向量output reg [3:0] flags // 4位寬的輸出向量,用于標志位
);// 向量拼接
always @(data_in) begindata_out = {data_in, data_in}; // 將data_in拼接到自身,形成16位的向量
end// 向量部分選擇
always @(data_out) beginflags = data_out[15:12]; // 選擇data_out的高4位作為標志位
endendmodule

在這個例子中,data_in是一個8位寬的線網向量,可以表示一個字節的數據。data_out是一個16位寬的輸出向量,而flags是一個4位寬的的寄存器向量,可以表示4個控制信號。通過使用向量和相關的操作符,可以方便地對多位信號進行操作。

另外,當位寬大于 1 時,wire 或 reg 即可聲明為向量的形式。例如:

reg [3:0]      counter ;    //聲明4bit位寬的寄存器counter
wire [32-1:0]  gpio_data;   //聲明32bit位寬的線型變量gpio_data
wire [8:2]     addr ;       //聲明7bit位寬的線型變量addr,位寬范圍為8:2
reg [0:31]     data ;       //聲明32bit位寬的寄存器變量data, 最高有效位為0

對于上面的向量,我們可以指定某一位或若干相鄰位,作為其他邏輯使用。例如:

wire [9:0]     data_low = data[0:9] ;
addr_temp[3:2] = addr[8:7] + 1'b1 ;

參考資料:
編碼寶庫:Verilog 數據類型

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/10015.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/10015.shtml
英文地址,請注明出處:http://en.pswp.cn/web/10015.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

數據庫調優-數據庫優化

數據庫優化 如何發現復雜的SQL有問題&#xff1f; 一個個去explain嗎&#xff1f;你有沒有這樣的困惑&#xff0c;開發代碼運行順暢絲滑&#xff0c;上生產了卻卡的一逼&#xff1f; 哈哈&#xff0c;相信大家都會遇到這樣的問題&#xff01; sql 復制代碼 # 舉個栗子&…

4. 從感知機到神經網絡

目錄 1. 從感知機到神經網絡 2. 最簡單的神經網絡 3. 激活函數的引入 1. 從感知機到神經網絡 之前章節我們了解了感知機&#xff0c;感知機可以處理與門、非與門、或門、異或門等邏輯運算&#xff1b;不過在感知機中設定權重的工作是由人工來做的&#xff0c;而設定合適的&a…

【將Maven源改為國內阿里云鏡像源】

目錄 一、如何配置Maven鏡像源&#xff1f; 二、Idea中的Maven配置 ?三、項目與你本地倉庫和中央倉庫的聯系 一、如何配置Maven鏡像源&#xff1f; 1、打開你的Maven用戶設置文件(settings.xml)。默認情況下&#xff0c;該文件存在于你的用戶目錄下的.m2文件夾中。如果你沒…

小程序內使用web-view組件嵌套H5頁面,當H5頁面更換了內容后,小程序里的h5頁面不更新

這個問題是由于小程序緩存了H5的內容造成的&#xff0c;可以在H5鏈接后面拼接個參數&#xff0c;加上時間戳可做用于H5的版本號&#xff0c;這樣每次訪問都可以全新的鏈接展示內容避免緩存&#xff0c;代碼如下wxml&#xff1a; <view> <web-view src"{{urlpath…

Kafka 執行命令超時異常: Timed out waiting for a node assignment

Kafka 執行命令超時異常&#xff1a; Timed out waiting for a node assignment 問題描述&#xff1a; 搭建了一個kafka集群環境&#xff0c;在使用命令行查看已有topic時&#xff0c;報錯如下&#xff1a; [rootlocalhost bin]# kafka-topics.sh --list --bootstrap-server…

《機器學習by周志華》學習筆記-決策樹-01

本書中的「決策樹」有時指學習方法,有時指學得的樹。 1、基本流程 1.1、概念 基本流程,亦稱「判定樹」 決策樹(decision tree),是一種常見的機器學習方法。以二分類任務為例,我們希望從給定訓練數據集學得一個模型,用以對新樣例進行分離。 以二分類任務為例,可看作對…

一圖看懂 | 藍卓煤炭行業解決方案

煤炭是我國能源保障的“壓艙石,也是國民經濟中重要的支柱產業之一無論是發電、建材、造紙、冶金、化工等工業領域都離不開煤炭近年來&#xff0c;在“雙碳”及能源安全雙重背景下推動智能化技術與煤炭產業的融合發展提升煤礦安全生產能力的重要性與日俱增智慧礦山的建設已逐漸成…

CentOS 7安裝配置docker

CentOS 7、8安裝、配置docker 這里宿主機的型號選擇是centos7.9.2009的版本 1.宿主機關閉防火墻和selinux&#xff0c;配置ipv4 #設置SELinuxdisabled vim /etc/selinux/config SELinuxdisabled 查看防火墻狀態&#xff1a;firewall-cmd --state 關閉防火墻&#xff1a;syst…

selenium爬取TapTap評論

上一篇寫的beautifulsoup和request爬取出的結果有誤。首先&#xff0c;TapTap網頁以JS格式解析&#xff0c;且評論并沒有“下一頁”&#xff0c;而是每次加載到底部就要進行等待重新加載。我們需要做的&#xff0c;是模仿瀏覽器的行為&#xff0c;所以這里我們用Selenium的方式…

2024年數維杯B題完整代碼和思路論文講解與分析

2024數維杯數學建模完整代碼和成品論文已更新&#xff0c;獲取↓↓↓↓↓ https://www.yuque.com/u42168770/qv6z0d/bgic2nbxs2h41pvt?singleDoc# 2024數維杯數學建模B題45頁論文和代碼已完成&#xff0c;代碼為全部問題的代碼 論文包括摘要、問題重述、問題分析、模型假設、…

【項目實戰】使用Github pages、Hexo如何10分鐘內快速生成個人博客網站

文章目錄 一.準備工作1.安裝git2.安裝node安裝 cnpm 3.使用 GitHub 創建倉庫&#xff0c;并配置 GitHub Pages0.Github Pages是什么1. 在 GitHub 上創建一個新倉庫2. 創建您的靜態網站3. 啟用 GitHub Pages4. 等待構建完成5. 訪問您的網站 二. Hexo1.什么是Hexo2.安裝Hexo1. 安…

【MySQL】求和查詢,目標值int,但空數據時返回null的問題(Java)

問題分析 int selectDeviceMonthRepairCount(String deviceType, String month);<select id"selectDeviceMonthRepairCount" resultType"int">SELECT SUM(repair_count)FROM warranty_recordsWHERE device_type #{deviceType}AND nian_yue #{month…

【代碼筆記】高并發場景下問題解決思路

高并發指的是在單位時間內&#xff0c;瞬時流量激增&#xff0c;系統需要同時處理大量并行的請求或操作。這種情況通常出現在面向大量用戶或服務的分布式系統中&#xff0c;尤其是當用戶請求高度集中時&#xff0c;比如促銷活動、秒殺活動、注冊搶課、熱點事件、定時任務調度等…

Maven 插件使用

1.spring-boot-maven-plugin 我們直接使用 maven package &#xff08;maven自帶的package打包功能&#xff09;&#xff0c;打包Jar包的時候&#xff0c;不會將該項目所依賴的Jar包一起打進去&#xff0c;在使用java -jar命令啟動項目時會報錯&#xff0c;項目無法正常啟動。…

開源相機管理庫Aravis例程學習(七)——chunk-parser

開源相機管理庫Aravis例程學習&#xff08;七&#xff09;——chunk-parser 簡介例程代碼函數說明arv_camera_create_chunk_parserarv_camera_set_chunksarv_chunk_parser_get_integer_value 簡介 本文針對官方例程中的&#xff1a;05-chunk-parser做簡單的講解。并介紹其中調…

kali linux更新卡在libc6:amd64 (2.37-15)

適配于linux的windows子系統&#xff0c;wsl2&#xff0c;安裝kali linux&#xff0c;運行 sudo apt update 卡在&#xff1a;Setting up libc6:amd64 (2.37-15) … 關機重啟、重新修復執行也不行 解決辦法&#xff1a;kill當前apt進程或者關機重啟kali-linux&#xff0c;然…

【系統架構師】-選擇題(十二)計算機網絡

1、網閘的作用&#xff1a;實現內網與互聯網通信&#xff0c;但內網與互聯網不是直連的 2、管理距離是指一種路由協議的路由可信度。15表示該路由信息比較可靠 管理距離越小&#xff0c;它的優先級就越高&#xff0c;也就是可信度越高。 0是最可信賴的&#xff0c;而255則意味…

MySQL變量的定義與使用(一)

一、標識符的命名規范 1、不能以數字開頭 2、不能使用關鍵字 3、只能使用_和$符號&#xff0c;不允許使用其他符號 二、定義MySQL變量的方法 set userName"鵝卵石"; #讀取變量 select userName as 名稱; #讀取時包含賦值操作 select userName:喜羊羊 as 賦值查詢名…

【JavaScript】內置對象 - 數組對象 ① ( 數組簡介 | 數組創建 | 數組類型檢測 )

文章目錄 一、數組對象1、數組簡介2、數組創建3、數組檢測 - Array.isArray() 方法4、數組檢測 - instanceof 運算符 Array 數組對象參考文檔 : https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array 一、數組對象 1、數組簡介 在 JavaScr…

(三十八)第 6 章 樹和二叉樹(二叉樹的二叉線索存儲)

1. 背景說明 2. 示例代碼 1) errorRecord.h // 記錄錯誤宏定義頭文件#ifndef ERROR_RECORD_H #define ERROR_RECORD_H#include <stdio.h> #include <string.h> #include <stdint.h>// 從文件路徑中提取文件名 #define FILE_NAME(X) strrchr(X, \\) ? strrc…