基于SparkRoad的Hdlbits学习(3)

Always Blocks

// 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 @*
        begin
            out_alwaysblock=a&b;
        end
endmodule

Alwaysblock2

// 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 @*begin
        out_always_comb=a^b;
    end
    always @(posedge clk)begin
        out_always_ff<=a^b;
    end
endmodule

此题要注意:
连续赋值(assign x=y;),只能在always块外使用。
阻塞赋值(x=y;),只能在always块内使用。
非阻塞赋值(x<=y;)只能在always块内使用。
(其实我试了一下,在这个地方的时序语句中,使用了阻塞赋值也可以运行)


If statement

// 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   ); 
    assign out_assign=(sel_b1&sel_b2)?b:a;
    always @* begin
        if (sel_b1&sel_b2==1'b1) begin
            out_always=b;
        end
        else out_always=a;
    end
endmodule

If sattement latches

// 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)
           shut_off_computer = 1;
        else
           shut_off_computer = 0;
    end

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

endmodule

这个问题在《夏宇闻Verilog》中有说明过,如果不对always模块中的if语句设计else,则会导致锁存器,所以还是补全为好。


Case statement

// 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:out=data0;
            3'b001:out=data1;
            3'b010:out=data2;
            3'b011:out=data3;
            3'b100:out=data4;
            3'b101:out=data5;
            default:out=3'b0;
        endcase
    end

endmodule

相对重要的就是case语句的声明要完全,其余情况要用default语句涵盖。


Priority

// synthesis verilog_input_version verilog_2001
module top_module (
    input [3:0] in,
    output reg [1:0] pos  );
    always@*begin
    casez(in)
        4'b0000:pos=2'b00;
        4'b???1:pos=2'b00;
        4'b??10:pos=2'b01;
        4'b?100:pos=2'b10;
        4'b1000:pos=2'b11;
    endcase
    end
endmodule

always语句别忘了写。


Priority encoder with casez

// synthesis verilog_input_version verilog_2001
module top_module (
    input [7:0] in,
    output reg [2:0] pos );
	always@*begin
        casez(in)
        	8'bzzzzzzz1:pos=0;
            8'bzzzzzz10:pos=1;
            8'bzzzzz100:pos=2;
            8'bzzzz1000:pos=3;
            8'bzzz10000:pos=4;
            8'bzz100000:pos=5;
            8'bz1000000:pos=6;
            8'b10000000:pos=7;
            default:pos=0;
        endcase
    end
endmodule

Avoiding latches

// 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
        left=0;down=0;right=0;up=0;
        case(scancode)
            16'he06b:left=1;
            16'he072:down=1;
            16'he074:right=1;
            16'he075:up=1;
        endcase
    end

endmodule

提出的赋初值确实是一种非常好的思路,避免了default的多次使用带来的麻烦,使用了赋初值就可以类似于先打好底子,在对需要改变的值再微操,在面对大数据时,大大减少了运算量。
而且default或者赋初值都是不可避免的,否则会产生锁存器。

posted @ 2023-05-25 14:25  江左子固  阅读(6)  评论(0编辑  收藏  举报