在Verilog语法中,向量可以按位(bit)引用,也可以部分引用,如:wire [7:0] a; 在使用向量a时,可以使用a[0], a[1],…a[7]; 也可以使用部分连续的位组成新的向量,如:a[7:6], a[4:3], a[2:1], a[5:3] 等。但如果使用不连续的位拼接起来是否可以呢?利用位拼接符可实现。
Verilog中 位拼接符是由一对花括号{} 实现的,在花括号内,任何位,矢量,常数都可以拼接起来。{}不仅可以拼接,而且还是有序的。例如: bit拼接可以形成新的向量,因此a[3:0] 可以写成 {a[3],a[2],a[1],a[0]}。下面介绍位拼接的一些用法:
- 位拼接可以实现多个位的组合形成新的变量向量,参加运算。如: {a[3:2},a[0],a[1]}, {a[3:0],b[3:0]} ,{a[3:0],1’b0} 等。
- 位拼接可以嵌套,如:
{a[3:2],{4{2’b01}} } 等效为{a[3:2],8’b01010101},即 四个2’b01拼接在一起。也可以向量嵌套,{3{a[3:2]}}等效为{a[3:2],a[3:2],a[3:2]}。
- 参与赋值运算
移位寄存器的使用:
例:
module shift8
(
input clk,
input load,
input [7:0] a,
output [7:0] c
);
reg [7:0] shift_r;
assign c = shift_r;
always@(posedge clk)
if(load)
shift_r <= a;
else
shift_r <= {shift_r[6:0], shift_r[7]};
endmodule
上例就是利用位拼接的方式实现循环左移,如果要实现循环右移只要将 shift_r<={shift_r[6:0],shift_r[7]};改成 shift_r<={shift_r[0],shift_r[7:1]};即可。由于在CPU的开发中,会经常用到各种移位,下面列举利用位拼接实现的移位:
(a)循环左移
shift_r <= {shift_r[6:0], shift_r[7]};
(b)循环右移
shift_r <= {shift_r[0],shift_r[7:1]};
(c)逻辑左移
shift_r <= {shift_r[6:0], 1’b0};
(d)逻辑右移
shift_r <= {1’b0, shift_r[7:1]};
(e)算术左移
shift_r <= {shift_r[7],shift_r[5:0],1’b0};
(f)算术右移
shift_r <= {shift[7], shift_r[7:1]};
进位位的使用:如四位全加器的代码
assign {co,y} = a + b + ci;
注意:如果有常量参与位拼接,不能用在赋值语句的左边。
对应视频:
学习本篇文章后有几点收获,1、位拼接运算符的功能很强大,用法非常灵活,可以代替实现逻辑左移、逻辑右移、算数左移、算数右移;2、巧妙运用位拼接功能,可以简化代码,实现时钟分频、LED循环点亮、重复bit位扩展,case语句条件拼接等等;
建议配合教学视频学习本篇文章,视频中扩展了大量使用技巧,非常棒!