zoukankan      html  css  js  c++  java
  • verilog

    本文为学习Verilog记录,可以当作小白入门,想看更多verlog知识,推荐博客:Reborn Lee


    变量部分

    变量类型

    • reg:此类型可以认为是一个寄存器,其可以保存值。
    • wire:此类型仅仅可以进行assign进行赋值,其可以认为是一根导线。
    • 对于模块定义中的变量,如果没有显式的说明类型,将会默认为wire类型。一般而言,对于输出变量,我们将会显式定义其为reg类型。
    module Insruction_Mem(
        input [31:0] addr,
        input R,
    	input CLK,
        output reg [31:0] data
       );
    

    变量定义以及使用

    //定义变量格式为:类型 [最高位:最低位] 变量
    wire [31:0] A;//定义一个32位的wire类型的变量
    A[2:0] = 0;   //将A的第0位到第2位均赋值为0
    A[2:0] = 3'b000;//同A[2:0] = 0
    

    定义变量时,需要说明变量的位,位的表示一般采用[最高位:最低位]的形式,且位的表示位于变量前方。

    如果不进行标注,将默认为1位。

    使用变量时,需要选取的位也采用[最高位:最低位]的形式,一般位于变量之后。

    一维数组的定义和使用

    //定义数组格式为:类型 [最高位:最低位] 变量 [最高位: 最低位]
    reg [31:0] data [31:0];//定义一个有32个32位reg型变量的数组
    //使用数组的格式为:类型 变量 [最高位:最低位]
    data[0][1:0] = 2'b00;//将data数组的第0号元素的第0位和第1位赋值为0
    

    定义数组时,采用以上形式,第一个位的表示说明该数组中每个变量的位,第二个位的表示说明数量。

    对于数组的更多知识,请参见博客Verilog中的多维数组和存储器


    模块部分

    模块的构成

    一个模块通常由以下几个部分构成

    • 变量的定义。

    • 变量的初始化。

    • 触发部分,即,当特定变量改变时,对模块内reg型变量的修改。

    • 赋值部分,即,对wire输出变量的赋值,此部分赋值不分先后,同时发生。

    //本人写的一个很冗余的代码,可能通过调用模块可以简化,但懒~
    module Registers(
        input [31:0] in,
        input W,
        input [31:1] Write,
        output [1023:0] out ,
        input CLK
        );
        
        //变量的定义部分
    	reg [31:0]  data [31:0];
        reg [5:0] i; 
        
    	//变量的初始化部分
    	initial 
          begin//verilog中所有的括号均使用begin,end
    	     for(i = 0; i < 32;i = i+1)
    		   begin
    		     data[i] = 0;
    		   end
    	  end
        
    	//触发部分
    	always @(posedge CLK)
    	begin
    	  if(W)
           begin		
    	     for(i = 1; i < 32;i = i+1)
    	       begin
    	         if(Write[i])
    		       begin
    		        data[i] = in;
    		       end
    	       end
    	   end
        end
        
    	//赋值部分
        //这里需要采用特殊的循环结构
    	genvar j;
    	generate for(j=0; j<32; j=j+1 ) 
    	begin:Reg
    		   assign out[j*32 + 31:j*32] = data[j];
        end endgenerate
    endmodule
    

    变量的初始化

    initial
      begin
         具体变量的赋值
      end
    

    触发部分

    always @(触发变量)
      begin
        被触发后,需要更改的变量
      end
    
    always @(posedge CLK)//时钟端上升沿触发
    always @(negedge CLK)//时钟端上升沿触发
    always @(*)//所有输出变量改变会触发
    always @(变量1,变量2)//其中变量改变会触发
    

    赋值部分

    assign 被赋值的变量 = 赋值变量或者常量;//赋值变量必须为reg类型
    

    特殊函数举例

    case

    module  Alu ( f, a, b, select);
         input  [2:0] select;
         input  [3:0] a, b;
         output  [4:0] f;
    
        reg [4:0] f;
        always @(*)
             begin
                  case (select)
                      3′b000 :  f = a;
                      3′b001 :  f = a + b;
                      3′b010 :  f = a - b;
                      3′b011 :  f = a / b;
                      3′b100 :  f = a % b;
                      3′b10 1:  f = a << 1;
                      3′b110 :  f = a >> 1;
                      3′b11 1:  f = a >b;
                      default:  f = 5′b00000 ;
                 endcase
            end
    endmodule
    

    generate for赋值循环

    Generate for 的主要功能就是对assign进行复制。

    genvar i; //变量定义
    generate for(i=0; i<4; i=i+1 ) 
        begin : begin_end块名称 
            assign赋值语句
        end endgenerate
    
    genvar j;
    generate for(j=0; j<32; j=j+1 ) 
        begin:Reg
    		assign out[j*32 + 31:j*32] = data[j];
        end endgenerate
    

    读取函数

    $readmemh("文件名", 变量);//以16进制进行读取
    $readmemb("文件名", 变量);//以2进制进行读取
    
    module  memory ();
      reg [7:0] my_memory [0:255];
      initial begin
        $readmemh("memory.list", my_memory);
      end
    endmodule
    
    //  Comments are allowed (wolf点评:段注释也可以,空行空格不影响!)
    CC         // This is first address i.e 8'h00
    AA         // This is second address i.e 8'h01
    @55        // Jump to new address 8'h55,@将会进行跳转
    5A         // This is address 8'h55
    69         // This is address 8'h56
    

    参见博客读取函数

    符号位扩展

    被扩展的变量 = {{(mwidth-cwidth){变量[cwidth-1]}},变量}
    //变量[cwidth-1]表示需要扩展的位
    //(mwidth-cwidth)需要扩展的数量
    //注意大括号
    
    module Extend16to32(
        input [15:0] in,
        output [31:0] out
        );
    
        assign out = {{16{in[15]}},in};
    
    endmodule
    

    利用变量读取变量的某些位

    一般而言,是不可以在变量的位选择中使用变量的,但是采用下面的结构可以

    a[BASE +:(/-:)WIDTH]
    
    mem = in [op*32+31 : op*32];//会报错
    mem = in [(op*32+31) -: 31];//不会报错
    

    参见博客verilog通过中+:与-:解决变量内固定长度数据位的动态选取


    仿真

    一般而言,对于仿真文件,我们只需要修改其中的测试部分,常用的语句如下:

    #100; 变量的赋值//100ms之后进行的操作
    #100; CLK = 1;
    #100; CLK = 0; in = 10; W = 1;
    #100; CLK = 1; in = 10; W = 0;
    
    always #10 变量的赋值//每10ms,执行一次变量的赋值
    always #10 CLK = ~CLK;
    always #20 Write =  Write << 1;
    always #100 in = in + 100;
    
  • 相关阅读:
    iptables 学习
    linux frp 配置
    LINUX下安装TOMCAT 及JDK方法
    更改默认源pip
    重装ORACLE参考
    pandas入门学习
    python笔记
    redis 笔记
    STM32工程编译后TIM1时钟变慢的解决
    IAR工程编译错误问题
  • 原文地址:https://www.cnblogs.com/zqybegin/p/13951803.html
Copyright © 2011-2022 走看看