Verilog 语法练习:HDL Bits做题笔记(第二章 Verilog Language)

2.4、Procedures

目录

2.4、Procedures

2.4.1、Always blocks(combinational)

 2.4.2、always blocks (clocked)

2.4.3 if statement

2.4.4、 if statement latches

2.4.5、Case statement:

2.4. 6、Priority encoder

2.4.7、Priority encoder with casez:

2.4.8、Avoiding latches:


2.4.1、Always blocks(combinational)

problem statement:

           Since digital circuits are composed of logic gates connected with wires, any circuit can be expressed as some combination of modules and assign statements. However, sometimes this is not the most convenient way to describe the circuit. Procedures (of which always blocks are one example) provide an alternative syntax for describing circuits.

For synthesizing hardware, two types of always blocks are relevant:

  • Combinational: always @(*)
  • Clocked: always @(posedge clk)

 Build an AND gate using both an assign statement and a combinational always block. (Since assign statements and combinational always blocks function identically, there is no way to enforce that you're using both methods. But you're here for practice, right?...)

solution:

// 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
        if(a==1&&b==1)
            out_alwaysblock<=1;
        else
            out_alwaysblock<=0;
    end       
endmodule

注:always语句中使用非阻塞赋值。 

 2.4.2、always blocks (clocked)

 problem statement:

Build an XOR gate three ways, using an assign statement, a combinational always block, and a clocked always block. Note that the clocked always block produces a different circuit from the other two: There is a flip-flop so the output is delayed.

 

 solution:

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

注:该题为我们展示了连续赋值语句  过程赋值语句中的非阻塞赋值和阻塞赋值的区别 。

2.4.3 if statement

problem statement:

 Build a 2-to-1 mux that chooses between a and b. Choose b if both sel_b1 and sel_b2 are true. Otherwise, choose a. Do the same twice, once using assign statements and once using a procedural if statement.

 

solution:

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

注意assign赋值语句后的问号表达式为真时,则out_assign=b否则out_assign=a

2.4.4、 if statement latches

problem statement:

 

solution:

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

 缺少else

2.4.5、Case statement:

problem statement:

 

Case statements are more convenient than if statements if there are a large number of cases. So, in this exercise, create a 6-to-1 multiplexer. When sel is between 0 and 5, choose the corresponding data input. Otherwise, output 0. The data inputs and outputs are all 4 bits wide.

Be careful of inferring latches (See.always_if2)

solution:

// 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)
            0:out=data0;
            1:out=data1;
            2:out=data2;
            3:out=data3;
            4:out=data4;
            5:out=data5;
            default:out=0;
        endcase
    end

endmodule

注:case的语法练习,注意不要丢掉endcase 

2.4. 6、Priority encoder

problem statement:

priority encoder is a combinational circuit that, when given an input bit vector, outputs the position of the first 1 bit in the vector. For example, a 8-bit priority encoder given the input 8'b10010000 would output 3'd4, because bit[4] is first bit that is high.

Build a 4-bit priority encoder. For this problem, if none of the input bits are high (i.e., input is zero), output zero. Note that a 4-bit number has 16 possible combinations.

Using hexadecimal (4'hb) or decimal (4'd11) number literals would save typing vs. binary (4'b1011) literals.

solution:

// synthesis verilog_input_version verilog_2001
module top_module (
    input [3:0] in,
    output reg [1:0] pos  );
always @(*) begin
    casez (in[3:0])
        4'bzzz1: pos = 0;   // in[3:1] can be anything
        4'bzz10: pos = 1;
        4'bz100: pos = 2;
        4'b1000: pos = 3;
        default: pos = 0;
    endcase
end
endmodule

2.4.7、Priority encoder with casez:

problem statement:

 

Build a priority encoder for 8-bit inputs. Given an 8-bit vector, the output should report the first bit in the vector that is 1. Report zero if the input vector has no bits that are high. For example, the input 8'b10010000 should output 3'd4, because bit[4] is first bit that is high.

From the previous exercise (always_case2), 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.

A case statement behaves as though each item is checked sequentially (in reality, it does something more like generating a giant truth table then making gates). Notice how there are certain inputs (e.g., 4'b1111) that will match more than one case item. The first match is chosen (so 4'b1111 matches the first item, out = 0, but not any of the later ones).

  • There is also a similar casex that treats both x and z as don't-care. I don't see much purpose to using it over casez.
  • The digit ? is a synonym for z. so 2'bz0 is the same as 2'b?0
  • Binary literals have to be used here because you need to specify z for some bits.

solution:

// synthesis verilog_input_version verilog_2001
module top_module (
    input [7:0] in,
    output reg [2:0] pos  );
    always@(*)
        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
endmodule

 注意关键字是casez不是case

2.4.8、Avoiding latches:

 problem statement:

Suppose you're building a circuit to process scancodes from a PS/2 keyboard for a game. Given the last two bytes of scancodes received, you need to indicate whether one of the arrow keys on the keyboard have been pressed. This involves a fairly simple mapping, which can be implemented as a case statement (or if-elseif) with four cases.

Your circuit has one 16-bit input, and four outputs. Build this circuit that recognizes these four scancodes and asserts the correct output.

To avoid creating latches, all outputs must be assigned a value in all possible conditions (See also always_if2). Simply having a default case is not enough. 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: 

 solution:

// 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;
            default:up=1'b0;
            		
        endcase
    end
endmodule

可以用十六进制表示scancode 

 

 

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值