请选择 进入手机版 | 继续访问电脑版
搜索
查看: 505|回复: 0

Verilog极简教程

[复制链接]

295

主题

295

帖子

4747

积分

论坛元老

Rank: 8Rank: 8

积分
4747
发表于 2018-4-3 22:25 | 显示全部楼层 |阅读模式



简明目录

教程说明
运行环境
RTL: 模块声明与例化(Module)
RTL: 常数
RTL: 变量(wire, reg)
RTL: 运算符
RTL: 函数(function)
RTL: 存储器(SRAM)
RTL: 存储器(ROM)
TB : 仿真精度(timescale)
TB : 任务(task)
TB : 时钟与复位产生(clock_reset_gen)
TB : 波形文件产生(wave_dump)
TB : 存储器初始化(mem_init)
RUN : Makefile
RUN : sim.do

1


教程说明

这是Verilog的一份极简教程,涵盖日常设计中的大部分基本语法。

语法不重要。

关键是实践。


2


运行环境

  1. <p># Centos Linux release 7.2.1511 </p><p>cat /etc/redhat-release</p><p>
  2. </p><p># QuestaSim-64 vlog 10.4c </p><p>vlog -version</p><p>
  3. </p><p># Verdi 2001</p><p>verdi</p>
复制代码



3


RTL: 模块声明与例化(Module)

使用ANSI-C风格端口列表
参数化
input都是wire
output可以是wire或者reg
最后一个port没有,
使用名称关联的方式例化
  1. <p>module mini_top #(</p><p>    parameter NUM=8</p><p>)(</p><p>    input             clk,       </p><p>    input             rst_n,     </p><p>    input  [15 :0]    i_cw,      </p><p>    output reg        o_flag,    </p><p>    output [NUM-1:0]  o_data_rd</p><p>);</p><p>
  2. </p><p>// module instantiation </p><p>wire [15:0] cw;</p><p>wire        flag;</p><p>wire [15:0] data_rd;</p><p>
  3. </p><p>mini_top #(</p><p>    .NUM ( 16 )</p><p>) u_DUT (</p><p>    .clk       ( clk      ) ,</p><p>    .rst_n     ( rst_n    ) ,</p><p>    .i_cw      ( cw       ) ,</p><p>    .o_flag    ( flag     ) ,</p><p>    .o_data_rd ( data_rd  ) </p><p>);</p>
复制代码



4


RTL: 常数

使用define定义全局常数
使用localparam 定义局部常数
使用include统一管理
尽量避免hard-coded number
  1. <p>`define NUM_1 8'b0001_1111</p><p>`define NUM_2 8'h1F</p><p>`define NUM_3 8'd31</p><p>`define NUM_4 {4'h1, 4'b1111}</p><p>`define NUM_5 {4'h1, {4{1'b1}}}</p><p>
  2. </p><p>localparam NUM_6 = 31;</p><p>localparam NUM_7 = NUM_6;</p><p>localparam NUM_8 = `NUM_1;</p><p>localparam NUM_9 = `NUM_1 + NUM_6 - 31;</p><p>
  3. </p><p></p>
复制代码

5


RTL: 变量(wire, reg)

给变量起个合适的名字
wire只用于组合逻辑
wire赋值方式:assign,模块例化
reg阻塞赋值描述组合逻辑
reg非阻塞赋值描述时序逻辑
  1. <p>wire r_enable;</p><p>wire r_start;</p><p>wire r_stop; </p><p>wire r_invert;</p><p>wire r_skip;</p><p>
  2. </p><p>assign {</p><p>    r_enable,</p><p>    r_start,</p><p>    r_stop,</p><p>    r_invert,</p><p>    r_skip</p><p>} = i_cw[4:0];</p><p>
  3. </p><p>// reg</p><p>// combinational logic</p><p>
  4. </p><p>reg flag;</p><p>always @* begin</p><p>    flag = r_enable | r_skip | r_stop | r_invert;</p><p>end</p><p>
  5. </p><p>// reg </p><p>// sequential logic</p><p>reg       cnt_4b_is_0xa;</p><p>reg [3:0] cnt_4b;</p><p>
  6. </p><p>always @ (posedge clk or negedge rst_n) begin</p><p>    if(~rst_n) begin</p><p>        cnt_4b        <= 4'd0;</p><p>        cnt_4b_is_0xa <= 1'b0;</p><p>        o_flag        <= 1'b0;</p><p>    end</p><p>    else begin</p><p>        cnt_4b        <= cnt_4b + 4'd1;</p><p>        cnt_4b_is_0xa <= cnt_4b==4'ha ? 1'b1 : 1'b0;</p><p>        o_flag        <= cnt_4b ==4'h8 ? 1'b1 : 1'b0;</p><p>    end</p><p>end</p>
复制代码



6


RTL: 运算符


用括号保证优先级
优先级顺序表从高到低
  1. <p>high: () [] {}</p><p>h0: ! ~</p><p>h1: * / %</p><p>h2: + -</p><p>h3: << >></p><p>h4: < <= > >=</p><p>h5: == != === !==</p><p>h6: &</p><p>h7: ^ ^~</p><p>h8: |</p><p>h9: &&</p><p>h10: ||</p><p>low: ? :</p><p>
  2. </p><p></p>
复制代码

7


RTL: 函数(function)


可综合
在模块中定义
至少包含一个输入
不能有输出
函数定义中不能出现always块语句
函数定义中可以调用函数
// function : max
  1. <p>// </p><p>function [7:0] max;</p><p>    input [7:0] A;</p><p>    input [7:0] B;</p><p>
  2. </p><p>    begin</p><p>        max = A < B ? B : A;</p><p>    end</p><p>endfunction</p><p>
  3. </p><p>wire [7:0] temp_max;</p><p>
  4. </p><p>assign temp_max = max(i_din[7:0], NUM_6);</p><p></p>
复制代码


8


RTL: 存储器(SRAM)


可仿真,可综合,可用于fpga
使用工艺库的memory compiler
  1. <p>module mini_sp_ram #(</p><p>    parameter ADDR_BITS=8</p><p>)(    </p><p>    input             clk,</p><p>    input      [ 7:0] addr,</p><p>    input      [ 7:0] din,</p><p>    input             ce,</p><p>    input             we,</p><p>    output reg [ 7:0] dout</p><p>);</p><p>
  2. </p><p>localparam MEM_DEPTH= 1<<ADDR_BITS;</p><p>
  3. </p><p>reg [7:0] mem[MEM_DEPTH-1:0];</p><p>
  4. </p><p>// synopsys_translate_off</p><p>integer i;</p><p>initial begin</p><p>    for(i=0; i<MEM_DEPTH;i=i+1) begin</p><p>        mem[i] = 8'h00;</p><p>    end</p><p>end</p><p>// synopsys_translate_on</p><p>
  5. </p><p>always @(posedge clk) begin</p><p>    if(ce & we) begin</p><p>        mem[addr] = din;</p><p>    end</p><p>end</p><p>
  6. </p><p>always @(posedge clk) begin</p><p>    if(ce && (!we)) begin</p><p>        dout <= mem[addr];</p><p>    end</p><p>end</p><p>
  7. </p><p>endmodule</p>
复制代码



9


RTL: 存储器(ROM)

可仿真,可综合,可用于fpga
使用工艺库的memory compiler
  1. <p>module mini_rom (    </p><p>    input             clk,</p><p>    input      [ 7:0] addr,</p><p>    output reg [ 7:0] dout</p><p>);</p><p>
  2. </p><p>always @(posedge clk) begin</p><p>    case(addr)</p><p>        8'h00: dout <= 8'h0A;</p><p>        8'h01: dout <= 8'h1A;</p><p>        8'h02: dout <= 8'h2A;</p><p>        8'h03: dout <= 8'h3A;</p><p>        8'h04: dout <= 8'h4A;</p><p>        8'h05: dout <= 8'h5A;</p><p>        8'h06: dout <= 8'h6A;</p><p>        8'h07: dout <= 8'h7A;</p><p>        8'h08: dout <= 8'h8A;</p><p>        8'h09: dout <= 8'h9A;</p><p>        8'h0A: dout <= 8'hAA;</p><p>        8'h0B: dout <= 8'hBA;</p><p>        8'h0C: dout <= 8'hCA;</p><p>        8'h0D: dout <= 8'hDA;</p><p>        8'h0E: dout <= 8'hEA;</p><p>        8'h0F: dout <= 8'hFA;</p><p>
  3. </p><p>        8'h10: dout <= 8'h50;</p><p>        8'h11: dout <= 8'h51;</p><p>        8'h12: dout <= 8'h52;</p><p>        8'h13: dout <= 8'h53;</p><p>        8'h14: dout <= 8'h54;</p><p>        8'h15: dout <= 8'h55;</p><p>        8'h16: dout <= 8'h56;</p><p>        8'h17: dout <= 8'h57;</p><p>        8'h18: dout <= 8'h58;</p><p>        8'h19: dout <= 8'h59;</p><p>        8'h1A: dout <= 8'h5A;</p><p>        8'h1B: dout <= 8'h5B;</p><p>        8'h1C: dout <= 8'h5C;</p><p>        8'h1D: dout <= 8'h5D;</p><p>        8'h1E: dout <= 8'h5E;</p><p>        8'h1F: dout <= 8'h5F;</p><p>
  4. </p><p>        default: dout <= 8'hff;</p><p>    endcase</p><p>end</p><p>
  5. </p><p>endmodule</p>
复制代码




10


TB : 仿真精度(timescale)

或者在仿真器命令选项指定
`timescale 1ns/10ps




11


TB : 任务(task)

不可综合
  1. <p>task hello;</p><p>    begin</p><p>        $display("hello world.");</p><p>    end</p><p>
  2. </p><p>endtask</p><p>
  3. </p><p>initial begin</p><p>    hello;</p><p>end</p>
复制代码




12


TB : 时钟与复位产生(clock_reset_gen)
  1. <p>
  2. </p><p>
  3. </p><p>reg clk;</p><p>reg rst_n;</p><p>
  4. </p><p>initial begin</p><p>    clk = 0;</p><p>end</p><p>
  5. </p><p>// Be careful if CLOCK_CYCLE%2 !=0</p><p>always #(`CLOCK_CYCLE/2) clk=~clk;</p><p></p>
复制代码



13


TB : 波形文件产生(wave_dump)

  1. <p>// use +define+DUMP_FSDB in vsim command</p><p>// to enable fsdb file dump</p><p>//</p><p>// -pli $(VERDI_HOME)/share/PLI/MODELSIM/$PLATFORM/novas_fli.so </p><p>//</p><p>`ifdef DUMP_FSDB </p><p>initial begin</p><p>    $fsdbDumpfile("tb.fsdb");</p><p>    $fsdbDumpvars(0,tb);</p><p>    #`MAX_RUN_TIME</p><p>    $finish(2);</p><p>end</p><p>`endif</p><p></p>
复制代码



14


TB : 存储器初始化(mem_init)

  1. <p>// memory initilization</p><p>integer fp_dmem;</p><p>
  2. </p><p>initial begin</p><p>    fp_dmem = $fopen(`MEM_INIT_FILE, "r");</p><p>    if(fp_dmem)</p><p>        #5 $readmemh(`MEM_INIT_FILE, `MEM_INST);</p><p>    else begin</p><p>        $display("%s open failed.",`MEM_INIT_FILE);</p><p>        $finish;</p><p>    end</p><p>end</p><p></p>
复制代码


15


  1. <p>RUN : Makefile</p><p>
  2. </p><p>PROJ_PATH = ../..</p><p>
  3. </p><p>RTL_PATH  = $(PROJ_PATH)/rtl</p><p>
  4. </p><p>TB_PATH   = $(PROJ_PATH)/sim/tb</p><p>
  5. </p><p>FILE_LIST = rtl.f</p><p>
  6. </p><p>DOFILE    = sim.do</p><p>
  7. </p><p>TB_TOP    = tb</p><p>
  8. </p><p>sim: </p><p>    @rm -rf work</p><p>    vsim -c -do $(DOFILE) </p><p>
  9. </p><p>verdi: </p><p>    @verdi -nologo -f $(FILE_LIST) -top $(TB_TOP) &</p><p>
  10. </p><p>clean:</p><p>    @rm -rf *.ini *.fsdb *.log verdiLog transcript work </p><p>
  11. </p><p>veryclean: clean </p><p> </p><p>listfile:</p><p>    @ls $(RTL_PATH)/*.v  > $(FILE_LIST)</p><p>    @ls $(TB_PATH)/*.v  >> $(FILE_LIST)</p>
复制代码




16
  1. <p>
  2. </p><p>
  3. </p><p>RUN : (sim.do)</p><p>
  4. </p><p>
  5. </p><p>vlib work</p><p>vmap work work</p><p>
  6. </p><p>vlog -timescale=1ns/1ps +incdir=./ -work work \</p><p>    +define+DUMP_FSDB \</p><p>    -f rtl.f</p><p>
  7. </p><p>vsim +notimingchecks -t 1ps -novopt -L work -l tb.log \</p><p>    -pli $env(VERDI_HOME)/share/PLI/MODELSIM/LINUX64/novas_fli.so \</p><p>    work.tb</p><p>
  8. </p><p>run -all</p>
复制代码


作者: ic7x24 不忘出芯
出处:http://mp.weixin.qq.com/s/-TpkQq0YxJkRZNqk7iIs_w

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

站长推荐上一条 /2 下一条

QQ|小黑屋|手机版|Archiver|OpenHW技术社区

GMT+8, 2018-7-21 15:52 , Processed in 0.112452 second(s), 6 queries , MemCache On.

Powered by Discuz! X3.4

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表