September 16, 2016
作者:dengshuai_super
出處:http://blog.csdn.net/dengshuai_super/article/details/52557422
聲明:轉載請註明作者及出處。
可綜合文件放到design文件夾下,testbench文件放到sim文件夾下(文件夾名可自定義)
//ex_module.v
module ex_module(
input wire sclk,
input wire rst_n,
input wire [7:0] d,//聲明模塊的時候,輸入一定是wire變量
output reg [7:0] q//聲明模塊的時候,輸出可以是wire變量也可以是reg;reg變量必須在always塊裏面賦值
);//接口列表
//異步的D觸發器
always @(posedge sclk or negedge rst_n) //括號裏面是敏感列表,可以包括電平觸發或者沿觸發
//寄存器發生變化或翻轉就是由CLK(讓D觸發器翻轉)或CLR(復位端讓寄存器清零)
if(rst_n == 1'b0) //if後面的括號裏是條件表,這裏是組合邏輯。"=="聲明一個比較器,"1"指的是1比特、"’"用來區分阿拉伯數字和進制,"b"代表的進制binary,“0”是一個比特的0
q<=8'h00; //10'b00000_00000 10'd10 10'hff,沿觸發的邏輯裏邊一定都用<=非阻塞賦值。
else
q<=d;
////同步
//always @(posedge sclk)//同步的時候sclk在上升沿的時候,檢測到低電平;異步的時候,當rst_n出現下降沿的時候,寄存器復位
// if(rst_n == 1'b0)
// q<=8'h00;
// else
// q<=d;
endmodule
//ex_wire.v
module ex_wire(
input wire sel,
input wire a,
input wire b,
output wire c
);//always 對reg賦值,assign語句(連續賦值)對wire賦值
//wire 變量一定用assign連續賦值語句賦值,而且必須是用阻塞賦值
assign c=(sel == 1'b1)?a:b;//(條件)?條件爲1:條件爲0
/*
if(sel == 1'b1)
c =a;
else
c =b;
*/
endmodule
//ex_cnt.v
module ex_cnt(
input wire sclk,//模擬晶振產生時鐘震盪
input wire rst_n,//模擬外部復位電平testbench
output wire [9:0] cnt
);
reg [9:0] cnt_r;//定義一個寄存器變量"r"代表reg
always @ (posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
cnt_r <= 10'd0;//"'d0"直接返回32位的0,截取低10位給cnt_r,1023+1=1024
else
cnt_r <= cnt_r + 1'b1;//0---1023-0---1023
assign cnt =cnt_r;
//仿真工具modelsim
//鏈接:http://pan.baidu.com/s/1qW5IhhM 密碼:n28z
endmodule
//請參考verilog數據常量
//數字表達式:<位寬><進制><數字>
//'b:二進制 //eg.4'b1110 表示4位二進制數1110
//'h:十六進制 //eg 8'hef、4’ha等
//'d:十進制 //eg 2'd3、4‘d15(不能寫16,4位寬最大15)等
//
//所以10’d0表示10位寬的數值0,0000000000
//加入10‘d15,則表示十進制15 ,0000001111
//tb_ex_cnt.v
//聲明延時單位,1ns指的是單位,100ps(0.1ns)指的是時標的精度。
//例如:#10.11--->10.10(最後的10ps精度被忽略)
`timescale 1ns/100ps
module tb_ex_cnt;//這是完整的頂層,沒有輸入輸出接口
reg tb_sclk,tb_rst_n;
wire [9:0] tb_cnt;
initial//一上電只被執行一次,在initial這個塊裏面只能被寄存器變量賦值
begin//在testbench裏面begin、and是順序執行的;在可綜合模塊裏面begin、and就是一個括號
tb_sclk <=0;
tb_rst_n<=0;//它倆有先後順序,先是tb_sclk被賦值然後再是tb_rst_n被賦值。但是之間的延遲是0。
#200.1
tb_rst_n<=1;
end
always #10 tb_sclk <= ~tb_sclk;//例如初始狀態是0,過了10ns變成1,又保持10ns變成0,周而復始的進行翻轉。於是產生了時鐘和復位信號
//例化的方法
//原始模塊名字 例化的名字(可以自定義)
ex_cnt ex_cnt_inst(
.sclk (tb_sclk),//模擬晶振產生時鐘震盪
.rst_n (tb_rst_n),//模擬外部復位電平testbench;例化模塊的時候如果原始模塊是輸入信號,那麼括號內可以是wire變量也可以是reg變量
.cnt (tb_cnt) //例化模塊的時候如果原始模塊是輸出信號,那麼括號內必須是wire變量(正好和可綜合模塊相反)
);
endmodule
例化時,變量的賦值應該遵循下圖(按照自己理解畫的,不一定正確,歡迎指正):
Design中的模塊輸出的時候可以作爲寄存器,它相當於把輸出寄存器的Q端直接連接到輸出口了,就把中間那根線給省略了;
Testbench中輸出變量必須是wire類型,因爲芯片畫PCB時,輸出的管腳都用線連。
打開ModelSim--->File--->new--->Project--->Project Name:ex_cnt(自定義,別寫中文);路徑:D:\VivadoProjects\FPGA_From_e_to_c\ex_1\sim(根據你文件的路徑寫)
--->在Project標籤頁下右鍵--->Add to Project--->Existing File--->將ex_cnt.v,tb_ex_cnt.v加進來--->Compile All--->數據編譯到Library標籤頁的work下
--->右鍵tb_ex_cnt--->Simulation without Optimization--->右鍵ex_cnt_inst,Add Wave--->
如圖所示:
在Wave 頁面下,如果左側信號欄變量名帶路徑,可以在Tools--->Window Preferences--->Display Signal Path改爲1即可。
然後在Wave頁面設置運行時間:這裏設置100us--->點擊Run--->在左側右擊變量--->Radix--->選擇顯示的進制。
Verilog中wire與reg類型的區別:
http://blog.csdn.net/changhaizhang/article/details/6933806
來源:
https://ke.qq.com/user/index/index.html#cid=66019&term_id=100056181