HDL_BITS 练习(五)

procedure:

1always block

assign 赋值的是个wire变量

always@(*) 赋值得到的是个reg变量

综合的结果不同

// synthesis verilog_input_version verilog_2001
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

2always block2

// synthesis verilog_input_version verilog_2001
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

3 if statement

if 的语法,用一个二选一选择器来做示例。

另外说了下if 语句综合和三目运算符?:的区别(一个综合结果是个reg ,另一个assign语句综合结果是wire变量

// synthesis verilog_input_version verilog_2001
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))
                begin
                    out_always=b;
                end
            else
                begin
                    out_always=a;
                end
        end
    assign out_assign=(sel_b1&&sel_b2)?b:a;
endmodule

4 if latch 

Verilog hdl 编写要有硬件思维,不能用软件思维来处理程序。if --else 必须写全。这和软件是不一样的。

What you must not do is write the code first, then hope it generates a proper circuit.

  • If (cpu_overheated) then shut_off_computer = 1;
  • If (~arrived) then keep_driving = ~gas_tank_empty;
  • The usual reason is: "What happens in the cases other than those you specified?". Verilog's answer is: Keep the outputs unchanged.
  • This behaviour of "keep outputs unchanged" means the current state needs to be remembered, and thus produces a latch

// synthesis verilog_input_version verilog_2001
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)begin
           shut_off_computer = 1;
        end
        else if(!cpu_overheated)begin
            shut_off_computer = 0;
        end
        
    end

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

endmodule
 

5 always case

case 语句非常类似C语言中的case用法。

6选一选择器

case十分容易,但是必须记得最后的default处理。否则会产生latch

// synthesis verilog_input_version verilog_2001
module top_module ( 
    input [2:0] sel, 
    input [3:0] data0,
    input [3:0] data1,
    input [3:0] data2,
    input [3:0] data3,
    input [3:0] data4,
    input [3:0] data5,
    output reg [3:0] out   );//

    always@(*) begin  // This is a combinational circuit
        case(sel)
            3'b000:begin
                out=data0;
            end
             3'b001:begin
                out=data1;
            end
             3'b010:begin
                out=data2;
            end
             3'b011:begin
                out=data3;
            end
             3'b100:begin
                out=data4;
            end
             3'b101:begin
                out=data5;
            end
            default:
                out=3'b000;
        endcase        
    end

endmodule

6 always case2

优先编码器

// synthesis verilog_input_version verilog_2001
module top_module (
    input [3:0] in,
    output reg [1:0] pos  );
    always@(*)
        begin
            case(in)
                4'b0000:pos=0;
                4'b0001:pos=0;
                4'b0010:pos=1;
                4'b0011:pos=0;
                4'b0100:pos=2;
                4'b0101:pos=0;
                4'b0110:pos=1;
                4'b0111:pos=0;
                4'b1000:pos=3;
                4'b1001:pos=0;
                4'b1010:pos=1;
                4'b1011:pos=0;
                4'b1100:pos=2;
                4'b1101:pos=0;
                4'b1111:pos=0;
                4'b1110:pos=1;
                default:pos=0;
            endcase       
        end
endmodule
7 casez

上一篇是四位输入,这次是8位输入,如果还是按照刚才的办法,将有256个cases,无疑不能这样编写程序。

there would be 256 cases in the case statement. We can reduce this (down to 9 cases) if the case items in the case statement supported don't-care bits. This is what casez is for: It treats bits that have the value z as don't-care in the comparison.

casez 就是为了用于忽略其他位的比较

// synthesis verilog_input_version verilog_2001
module top_module (
    input [7:0] in,
    output reg [2:0] pos  );
    always@(*)
        begin
            casez(in[7:0])
                8'bzzzzzzz1: pos = 3'd0;
                8'bzzzzzz1z: pos = 3'd1;
                8'bzzzzz1zz: pos = 3'd2;
                8'bzzzz1zzz: pos = 3'd3;
                8'bzzz1zzzz: pos = 3'd4;
                8'bzz1zzzzz: pos = 3'd5;
                8'bz1zzzzzz: pos = 3'd6;
                8'b1zzzzzzz: pos = 3'd7;
                default: pos = 3'd0;
            endcase
        end         
endmodule

8 always no latches

用if 语句,包含default并不保险。考虑在case之前初始化状态,则可以免去default

原文如下:

You must assign a value to all four outputs in all four cases and the default case. This can involve a lot of unnecessary typing. One easy way around this is to assign a "default value" to the outputs before the case statement:

always @(*) begin
    up = 1'b0; down = 1'b0; left = 1'b0; right = 1'b0;
    case (scancode)
        ... // Set to 1 as necessary.
    endcase
end

This style of code ensures the outputs are assigned a value (of 0) in all possible cases unless the case statement overrides the assignment. This also means that a default: case item becomes unnecessary.

程序:

// synthesis verilog_input_version verilog_2001
module top_module (
    input [15:0] scancode,
    output reg left,
    output reg down,
    output reg right,
    output reg up  );
    always@(*)
        begin
            up = 1'b0; down = 1'b0; left = 1'b0; right = 1'b0;
            //在case之前的初始化,即默认状态
    
        case(scancode)
            16'he06b:begin
                up = 1'b0; down = 1'b0; left = 1'b1; right = 1'b0;
            end
            
            16'he072:begin
                up = 1'b0; down = 1'b1; left = 1'b0; right = 1'b0;
            end
            
            16'he074:begin
                up = 1'b0; down = 1'b0; left = 1'b0; right = 1'b1;
            end
            
            16'he075:begin
                up = 1'b1; down = 1'b0; left = 1'b0; right = 1'b0;
            end
            
        endcase
        end
    
endmodule


 

上一篇:Element select选择器


下一篇:深入探讨,无服务器是新的 PaaS 吗?