Alwaysblock1

组合逻辑always块的使用,注意这里的wire和reg综合出来的结果是一样的,这里只是verilog语法导致二者声明不一样。

// 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

组合逻辑用阻塞赋值,时序逻辑用非阻塞赋值,这里与verilog仿真器追踪事件的原理有关,不遵循这一规则将导致很难发现模拟和综合出的硬件之间的非确定性和错误。

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

Always if

使用if语句来表示多路选择器.

// 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)
            out_always=b;
        else
            out_always=a;
    end
endmodule

Always if2

这一节告诉了怎么避免if语句综合出不期望的Latch,即把else的情况补全。

// 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

Always case

case语句的用法,注意case也要把所有条件覆盖,如写一个default,避免综合出不期望的latch。

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'd0:out=data0;
            3'd1:out=data1;
            3'd2:out=data2;
            3'd3:out=data3;
            3'd4:out=data4;
            3'd5:out=data5;
            default:out=0;
        endcase
    end

endmodule

Always case2

这一题是一个优先编码器,标准答案直接把所有情况都列出来了,我这里直接用了一个casex,即如果比较双方有一方的某些位的值是z或x,那么这些位的比较就不予考虑。

// synthesis verilog_input_version verilog_2001
module top_module (
    input [3:0] in,
    output reg [1:0] pos  );
    always@(*)
    begin
        casex(in)
            4'bxxx1:pos=2'd0;
            4'bxx10:pos=2'd1;
            4'bx100:pos=2'd2;
            4'b1000:pos=2'd3;
            default:pos=2'd0;
        endcase
    end
endmodule

Always casez8

这题是一个八位的有限编码器,这里教了casez的使用,和casex的使用是基本一致的,区别是case是全等比较,casez高阻态和0、1比较结果为1,与x比较结果为零,而casex中不定态与0、1、z比较结果均为1。

module top_module (
    input [7:0] in,
    output reg [2:0] pos );
    always@(*)
    begin
        casez(in)
            8'bzzzz_zzz1:pos=0;
            8'bzzzz_zz10:pos=1;
            8'bzzzz_z100:pos=2;
            8'bzzzz_1000:pos=3;
            8'bzzz1_0000:pos=4;
            8'bzz10_0000:pos=5;
            8'bz100_0000:pos=6;
            8'b1000_0000:pos=7;
            default:pos=0;
        endcase
    end

endmodule

Always nolatches

这里又使用了另外一种方法避免latch:即在组合逻辑块中赋初值。

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

 

内容来源于网络如有侵权请私信删除

文章来源: 博客园

原文链接: https://www.cnblogs.com/magnolia666/p/16819939.html

你还没有登录,请先登录注册
  • 还没有人评论,欢迎说说您的想法!