HDLBits(6)9.14

2 Verilog语言

2.4 程序

2.4.1 Always 模块1

组合逻辑:always @(*)

时序逻辑:always @(posedge clk)

对于组合逻辑电路,一般会用 * 代替所有输入变量,防止出现错误

assign 用于对线性信号赋值,always模块用于定义reg型信号(寄存器型)

always与assign存在一个细微的区别,

wire a;
reg b;
assign a = 1'b0;
always@(*)
    b = 1'b0;

在这种情况下,做仿真时a将会正常为0, 但是b却是不定态。always@(*)中的*是指该always块内的所有输入信号的变化为敏感列表,也就是仿真时只有当always@(*)块内的输入信号产生变化,该块内描述的信号才会产生变化,而像always@(*) b = 1'b0;

这种写法由于1'b0一直没有变化,所以b的信号状态一直没有改变,由于b是组合逻辑输出,所以复位时没有明确的值(不定态),而又因为always@(*)块内没有敏感信号变化,因此b的信号状态一直保持为不定态。

module top_module(
    input a, 
    input b,
    output wire out_assign,
    output reg out_alwaysblock
);
    assign out_assign = a&b;
    always @(*)
        out_alwaysblock = a&b;
endmodule

 

2.4.2 Always 模块2

三种赋值方法:

连续型:assign a=b不能在过程块中实现

过程阻塞型:x=y只能在过程块中实现,用于组合逻辑

过程非阻塞型:x<=y只能在过程块中实现,用于时序逻辑

使用以上三种方式,定义异或门(XOR)

module top_module(
    input clk,
    input a,
    input b,
    output wire out_assign,
    output reg out_always_comb,
    output reg out_always_ff   );
    assign out_assign = a^b;
    always @(*) out_always_comb = a^b;
    always @(posedge clk) out_always_ff <= a^b;
endmodule

 2.4.3 Always if

两种定义2选1选择器的方式

always @(*) begin
    if (condition) begin
        out = x;
    end
    else begin
        out = y;
    end
end
assign out = condition?x:y;

练习:定义逻辑如下表所示的选择器

 

module top_module(
    input a,
    input b,
    input sel_b1,
    input sel_b2,
    output wire out_assign,
    output reg out_always   ); 
    always @(*)
        begin
            if (sel_b1 & sel_b2)
                out_always = b;
            else
                out_always = a;
        end
    assign out_assign = sel_b1?(sel_b2?b:a):a;//两次选择逻辑
endmodule

 

2.4.4 Always if 2

//以下代码会生成锁存器产生错误,修改
module top_module (
    input      cpu_overheated,
    output reg shut_off_computer,
    input      arrived,
    input      gas_tank_empty,
    output reg keep_driving  );
always @(*) begin
    if (cpu_overheated)
       shut_off_computer = 1;
end
    
always @(*) begin
    if (~arrived)
       keep_driving = ~gas_tank_empty;
end
    
//修改后
module top_module (
    input      cpu_overheated,
    output reg shut_off_computer,
    input      arrived,
    input      gas_tank_empty,
    output reg keep_driving  ); //

    always @(*) begin
        if (cpu_overheated)
           shut_off_computer = 1;
        else
            shut_off_computer = 0;
    end

    always @(*) begin
        if (~arrived)
           keep_driving = ~gas_tank_empty;
        else 
            keep_driving = (~arrived);
    end

endmodule

 

posted @ 2022-09-14 22:26  LhTian21  阅读(52)  评论(0)    收藏  举报