HDLBits(3)8.24

2 Verilog语言

2.2 向量

2.2.4 逐位操作符(x)与逻辑操作符(xx)

逐位:对一个n bit输入向量进行逻辑运算,在n bit上逐位进行,并产生一个n bit长的结果

逻辑:任何类型的输入都会被视作布尔值,零->假,非零->真,将布尔值进行逻辑比较后,输出一个 1 bit的结果

eg:分别输出a,b逐位或;a,b逻辑或;a,b按位取反

    assign     out_or_bitwise = a | b;
    assign     out_or_logical = a || b;
    assign     out_not[2:0] = ~a;
    assign     out_not[5:3] = ~b;

 2.2.5 四输入门

多输入的逻辑门可以使用位展开的写法和缩减运算符的写法,如下:

    /* 缩减运算符 */
    assign out_and = & in;
    assign out_or  = | in;
    assign out_xor = ^ in;
    /* 位展开运算符 */
    assign out_and = in[3] & in[2] & in[1] & in[0];
    assign out_or  = in[3] | in[2] | in[1] | in[0];
    assign out_xor = in[3] ^ in[2] ^ in[1] ^ in[0];

2.2.6 向量串联运算符(连续操作符)

将较小的向量连接在一起,创建更大的向量 

基本语法:assign { a , b } = c;

一定要标注位宽,否则综合器不知道结果需要多少位宽

连接符既可用于赋值语句的右侧创造更大的向量,也可用于左侧奇偶啊换字节顺序,eg:

input  [15:0] in;
output [23:0] out;
assign {out[7:0], out[15:8]} = in;         // 连接符用于赋值语句左侧,交换了字节的顺序
assign out[15:0] = {in[7:0], in[15:8]};    // 连接符用于赋值语句右侧,交换了字节的顺序
assign out = {in[7:0], in[15:8]};          // 此语句作用上与上两句相同交换了字节顺序,但不同的是赋值语句右侧为16位
//赋予左值后,右值扩展为24位,高8位赋零,前两句中,高8位为未赋值状态

题目:

module top_module (
    input [4:0] a, b, c, d, e, f,
    output [7:0] w, x, y, z 
);    
    assign w = {a,b[4:2]};
    assign x = {b[1:0],c,d[4]};
    assign y = {d[3:0],e[4:1]};
    assign z = {e[0],f,2'b11};
    
endmodule

 

2.2.7 矢量反转

module top_module( 
    input [7:0] in,
    output [7:0] out
);
	assign {out[0],out[1],out[2],out[3],out[4],out[5],out[6],out[7]} = in;
endmodule

可以使用连接符来实现,但这种方法比较笨,不适用于较大位宽的向量,由于是多个重复操作,想到使用for循环来实现:

module top_module( 
    input [7:0] in,
    output [7:0] out
);
integer i;
always @(*) begin	
     for (i=0; i<8; i++)	//Use integer for pure Verilog.
	     out[i] = in[8-i-1];
end
endmodule

 首先创建循环变量i,注意,HDLBits 上的 solution 中,i 定义于 for 循环的括号中,这在 Verilog 的语法中是不被允许的,是 SystemVerilog 的语法,Verilog 的语法需要提前定义 integer 变量,即整形变量

再创建组合逻辑always块,

always块是Verilog中用来描述组合逻辑以及时序逻辑的语法,组合逻辑语法为:

always @ (level event) begin
	[multiple statements]
end

可以用 * 代替敏感信号,编译器会很具内部内容自动识别,达到简化的目的

值得注意的是,for 循环中的“循环”指的是代码层面的循环,而电路是不存在循环的,无论是信号而是门电路,都不存在循环。实际上,for 循环表示的代码将被综合器解析,for 循环将被分别解析为硬件电路。

除此之外,还可以使用generate 生成块(HDLBits提供的solution)

generate
    genvar i;
    for (i=0; i<8; i = i+1) begin: my_block_name			
        assign out[i] = in[8-i-1];
    end

 生成块与for循环的概念并不相同(一下全是复制粘贴,有待进一步理解)

for 循环和 Verilog 中其他的几种循环语句 while ,forever,repeat 本质上都用于控制语句的执行次数

生成块主要用于动态生成语句,例化 something(不只是例化模块),生成块与上述的过程块循环语句不同,并不是描述电路的一种行为。

生成块可以例化 assign 语句,模块,信号和变量的声明以及 always initial 这样的过程块。循环生成块是生成块中的一种类型,在综合过程中同样被综合器进行编译,这个过程可以看做综合过程中动态生成更多 Verilog 代码的预处理过程。在上面的例子中,generate 块在综合的过程中,综合了 8 句 assign 赋值语句

总的来说,for 循环强调了对电路的行为描述,在综合的过程中循环展开,而生成块则用于综合过程中,动态生成代码,两者有本质上的不同

而且再生成块中的 for 循环中不能像前例一样使用 integer 作为循环变量,而是必须使用 genvar 变量

posted @ 2022-08-24 09:33  LhTian21  阅读(80)  评论(0)    收藏  举报