Verilog基础语法(2)之标量和向量、多维数组和存储器

一、标量和向量

Verilog中常用的数据类型为wire、reg,两者都可以定义为一位变量和多位变量,其中一位的称为标量,多位的称为向量。

  • 1bit的时序器件即为一个触发器;16bit的时序器件即为一个能够存储16bit数据的存储器。
  • 若没有指定wire或reg的位宽,则认为1bit的标量;若指定了位宽,则wire或reg变成多比特实体向量。

1、表达方式

  wire        a1;          // 单比特wire型标量
  wire [7:0]  a2;          // 8-bit wire型矢量
  reg         a3;          // 单比特reg型变量
  reg  [31:0] a4;          // 32 bit 存储地址的矢量变量

2、位宽规范性

位宽的表达方式在上下代码中应统一风格,一般以最左边为最高位,最右边为最低位。

  wire  [msb:lsb]   b1;
  integer           msb_1;
 
  wire [15:0]       b2;      // 合法表达,msb = 15, lsb = 0
  wire [msb_1: 2]   b3;         // 非法表达

msb以及lsb可以是任何整数值–正负或零,不允许使用变量,而且Isb的值可以大于、等于或小于msb的值。但为了保持风格统一,也就是左边的值要比右边的值大,所以不建议lsb大于或等于msb。

3、位选择

向量中的各个位都是可以被单独选中进行操作,如赋值,运算等。例如:

  reg [7:0]      addr;         // 8-bit reg variable [7, 6, 5, 4, 3, 2, 1, 0]
 
  addr [0] = 1;                // assign 1 to bit 0 of addr
  addr [3] = 0;                // assign 0 to bit 3 of addr

结果示意图:
在这里插入图片描述

reg [31:0]    addr;
addr [23:16] = 8'h23;         // 23至16位被赋值为8'h23

在这里插入图片描述
若想要进行批量操作,可以使用:

[<start_bit> +: <width>]     // 选中宽度为start_bit再加上width
[<start_bit> -: <width>]     // 选中宽度为start_bit再减去width

例如:

module weikuan;
  reg [31:0]  data;
  int         i;
 
  initial begin
    data = 32'hFACE_CAFE;
    for (i = 0; i < 4; i = i+ 1) begin
      $display ("data[8*%0d +: 8] = 0x%0h", i, data[8*i +: 8]);
    end
 
    $display ("data[7:0]   = 0x%0h", data[7:0]);
    $display ("data[15:8]  = 0x%0h", data[15:8]);
    $display ("data[23:16] = 0x%0h", data[23:16]);
    $display ("data[31:24] = 0x%0h", data[31:24]);
  end
endmodule

仿真结果:

data[8*0 +: 8] = 0xfe              // 等价于 data [8*0+8 : 8*0]
data[8*1 +: 8] = 0xca              // 等价于 data [8*1+8 : 8*1]
data[8*2 +: 8] = 0xce              // 等价于 data [8*2+8 : 8*2]
data[8*3 +: 8] = 0xfa              // 等价于 data [8*3+8 : 8*3]

data[7:0]   = 0xfe
data[15:8]  = 0xca
data[23:16] = 0xce
data[31:24] = 0xfa

二、多维数组和存储器

在Verilog中,多维数组对应存储器,而向量可悲认为是一个深度为0的二维数组。
常用的二维数组有RAM、ROM等,主要由深度和位宽两个参数。

  reg        y1 [11:0];        // reg型数组,深度为12,位宽为1
  wire [7:0] y2 [3:0]          // wire型数组,深度为4,位宽为8
  reg  [7:0] y3 [0:1][0:3];    // reg型三维数组,2行(rows = 2)3列(cols = 3),每个单元数据位宽8bit

1、多维数组赋值

例子:

module mem();
  reg [7:0]  mem1;               // reg vector 8-bit wide
  reg [7:0]  mem2 [0:3];         // 8-bit wide vector array with depth=4
  reg [15:0] mem3 [0:3][0:1];   // 16-bit wide vector 2D array with rows=4,cols=2
 
  initial begin
    integer i;
 
    mem1 = 8'ha9;
    $display ("mem1 = 0x%0h", mem1);
 
    mem2[0] = 8'haa;
    mem2[1] = 8'hbb;
    mem2[2] = 8'hcc;
    mem2[3] = 8'hdd;
    for(i = 0; i < 4; i = i + 1) begin
      $display("mem2[%0d] = 0x%0h", i, mem2[i]);
    end
 
    for(int i = 0; i < 4; i += 1) begin
      for(int j = 0; j < 2; j += 1) begin
        mem3[i][j] = i + j;
        $display("mem3[%0d][%0d] = 0x%0h", i, j, mem3[i][j]);
      end
    end
  end
endmodule

仿真结果:

mem1 = 0xa9
mem2[0] = 0xaa
mem2[1] = 0xbb
mem2[2] = 0xcc
mem2[3] = 0xdd
mem3[0][0] = 0x0
mem3[0][1] = 0x1
mem3[1][0] = 0x1
mem3[1][1] = 0x2
mem3[2][0] = 0x2
mem3[2][1] = 0x3
mem3[3][0] = 0x3
mem3[3][1] = 0x4

2、RAM二维数组

mem为一个shendu256,位宽8bit的内存空间。
在这里插入图片描述

3、寄存器变量案例

  1. 一维数组案例:具体功能为:复位时,对寄存器赋0初值;当sel和wr有效时,将输入值赋给寄存器;其他情况,寄存器保持不变。
module dff(
		input		   clk,
		input          rst_n,
		input 		   wr,
		input 		   sel,
		input  [15:0]  wdata,
		output [15:0]  rdata	);
reg [15:0] reg;
always@(posedge clk or negedge rst_n)begin
	if(!rst_n)
		reg <= 16'b0;
	else begin
		if(sel & wr)
			reg <= wdata;
		else
			reg <= reg;
	end		
end
assign rdata = (sel & ~wr) ? reg : 16'b0;
endmodule
  1. 二维数组案列:
module mem(
		input		   clk,
		input          rst_n,
		input  [1:0]   addr,
		input 		   wr,
		input 		   sel,
		input  [15:0]  wdata,
		output [15:0]  rdata	);
		
reg [15:0]mem[3:0];
integer i;

always@(posedge clk or negedge rst_n)begin
	if(!rst_n)begin
		for(i = 0; i < 4; i = i + 1)begin
			mem[i] <= 16'b0; 
		end
	end
	else begin
		if(sel & wr)
			mem[addr] <= wdata;
		else
			mem[addr] <= mem[addr];
	end
end
assign rdata = (sel & ~wr) ? mem[addr] : 16'b0;
endmodule
  • 3
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
Verilog中,二维数组的使用有一些限制。首先,二维数组不能作为模块的输入输出端口。如果确实需要使用二维数组作为端口,只能通过将其等效展开为一维数组来代替。其次,在Verilog中初始化二维数组时,目前只能通过读入文件的方法或使用generate语句对二维数组进行初始化。这种定义方式相对较少见,因为在Verilog代码中通常不会涉及到二维数组的定义。然而,这种定义方法与C语言非常类似,它表示在内存中获得一个行数为256、列数为256,每个位宽为8的二维数组。这种定义方法可以将矩阵中的数值映射到二维数组的每个空间中,从另一方面来看,矩阵也可以看作是一个二维数组。例如,可以使用以下语句定义一个256x256的二维数组并赋值: reg [7:0 data [255:0 [255:0]; 其中,data是一个256x256的二维数组,每个元素的位宽为8。注意,这里的赋值方法仅用于示例,实际上在Verilog中初始化二维数组的方法可能会有所不同。例如,可以使用嵌套的for循环对二维数组进行赋值: reg [7:0 b [0:3 [0:3]; initial begin // 使用2D for循环进行赋值 for (int i=0; i<=3; i++) for (int j=0; j<=3; j++) b[i][j = i*j; end 这样,数组b中的每个元素b[i][j都会被赋值为i*j的结果。请注意,这只是一种正确的方法,实际上还有其他方法可以初始化二维数组。总之,在Verilog中,二维数组的使用可能会有一些限制,但可以通过合适的方法来定义和初始化二维数组。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [【verilog语法】二维数组](https://blog.csdn.net/carlsun80/article/details/77726060)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [【VerilogVerilog定义二维数组(2D Array)](https://blog.csdn.net/m0_61298445/article/details/123857581)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值