Menu Close

Verilog 变量声明与数据类型三(可变的向量域选择)

当我们定义了一个向量,在使用这个向量时,可能是整个向量全部都使用,也有可能只是使用向量的其中一部分。verilog 语言语法支持可变的向量域选择,方便用户的使用。

1.语法:(向量使用方法)

  • 向量名 [ 起始位 +: 位宽 ]   

在不改变原本向量声明的高低有效位顺序的情况下,从起始位开始(包括起始位), 宽度为位宽,从起始位位宽的一段向量区域。

例:

wire  [31 : 0] a;    a [0 +: 8] 等效为 a[7 : 0];  // 起始位 在最右侧

wire  [0 : 31] b;    b [0 +: 8] 等效为 b[0 : 7];  // 起始位 在最左侧

 

  • 向量名 [ 起始位 -: 位宽 ]

在不改变原本向量声明的高低有效位顺序的情况下,从起始位开始(包括起始位), 宽度为位宽,从起始位位宽的一段向量区域。

wire  [31 : 0] a;    a [7 -: 8] 等效为 a[7 : 0];  // 起始位 在最左侧

wire  [0 : 31] b;    b [7 -: 8] 等效为 b[0 : 7];  // 起始位 在最右侧

 

  • 起始位可以是变量,但位宽必须是常量

例:

for (i = 0; i < 4; i = i + 1)

a[(i*8) +: 8] = i;

 

例1:

`timescale 1ns / 1ps
module tb;

wire [7:0] a = 8'h7f;
reg  [3:0] b;

initial
begin
    b = a[0 +: 4];
    $display("time = %d, b = %h", $time, b);
    #10;

    b = a[3:0];
    $display("time = %d, b = %h", $time, b);
    #10;

    b = a[7 -: 4];
    $display("time = %d, b = %h", $time, b);
    #10;

    b = a[7:4];
    $display("time = %d, b = %h", $time, b);
    #10;
end

endmodule

仿真的结果:

time =  0, b = f
time = 10, b = f
time = 20, b = 7
time = 30, b = 7

2.向量定义

wire [63:0] a;    // a[0] 是最有效位, a[63] 是最有效位

reg  [0:63] b;     // a[0] 是最有效位, a[63] 是最有效位

例2:

`timescale 1ns / 1ps
module tb;
wire [63:0] a;    // a[0] 是最低有效位, a[63] 是最高有效位
reg  [0:63] b;    // a[0] 是最高有效位, a[63] 是最低有效位

assign a = 64'h0123_4567_89ab_cdef;
reg [23:0] c;

initial
begin
    b = 64'h0123_4567_89ab_cdef;

    c = a[31 -: 24]; // 从bit[31]位开始(包括bit[31]位), 宽度为24位。 相当于 c = a [31:08];
    $display ("time = %d, c = %h", $time , c );
    #10;

    c = a[ 8 +: 24]; // 从bit[8]位开始(包括bit[8]位), 宽度为24位。 相当于 c = a [31:08];
    $display ("time = %d, c = %h", $time , c );
    #10;

    c = b[31 -: 24]; // 从bit[31]位开始(包括bit[31]位), 宽度为24位。 相当于 c = b [08:31];
    $display ("time = %d, c = %h", $time , c );
    #10;

    c = b[ 8 +: 24]; // 从bit[8]位开始(包括bit[8]位), 宽度为24位。 相当于 c = b [08:31];
    $display ("time = %d, c = %h", $time , c );
    #10;

end

endmodule

控制台输出的结果:

time = 0, c = 89abcd

time = 10, c = 89abcd

time = 20, c = 234567

time = 30, c = 234567

 

可变的向量域选择通常用于向量的初始化赋值, 当然在平时使用时,也是可以用于赋值语句的。 可变的向量域选择是可仿真的, 也是可综合的语法。

例3:

`timescale 1ns / 1ps
module tb;
integer i;
reg [31:0] a;
reg [31:0] b;
initial
begin
    for (i = 0; i < 4; i = i + 1)
    begin
        a[(i*8) +: 8] = i;
    end
    #10;

    $display("a[31:24] = %h", a[31:24]);     
    $display("a[23:16] = %h", a[23:16]);     
    $display("a[15:08] = %h", a[15:08]);     
    $display("a[07:00] = %h", a[07:00]);  
    #10;

    b[31:24] = 3;
    b[23:16] = 2;
    b[15:08] = 1;
    b[07:00] = 0;

    #10;
  
    $display("b[31:24] = %h", b[31:24]);
    $display("b[23:16] = %h", b[23:16]);
    $display("b[15:08] = %h", b[15:08]);
    $display("b[07:00] = %h", b[07:00]);
end

endmodule

 

控制台输出结果:

a[31:24] = 03
a[23:16] = 02
a[15:08] = 01
a[07:00] = 00
b[31:24] = 03
b[23:16] = 02
b[15:08] = 01
b[07:00] = 00

 

我们会看到, 上个例子中, 如果使用可变向量选择, 会使得代码变得更加简洁灵活。特别是在for 循环中经常会使用可变向量域选择这种方式。

 

 

 

 

Posted in FPGA, FPGA, Verilog, Verilog, 教材与教案, 文章

发表评论

相关链接