Verilog HDL刷题笔记(03)

[注]这个网站比较神奇的一点就在于,不解出来就不让你看答案。所以经常一个错误卡好久。。不过有大佬在GitHub发过答案了:

https://github.com/M-HHH/HDLBits_Practice_verilog

---------

31.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.

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

32.The following code contains incorrect behaviour that creates a latch. Fix the bugs so that you will shut off the computer only if it's really overheated, and stop driving if you've arrived at your destination or you need to refuel.

 

 

// 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
        shut_off_computer=cpu_overheated;
    end
    always @(*) begin
        keep_driving=(~arrived)&(~gas_tank_empty);
    end
endmodule


//-2/if语句条件不全的话会有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)
            shut_off_computer = 1;
        else
            shut_off_computer = 0;
    end

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

33.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)

// 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;
            3'b110: out<=4'b0000;
            3'b111: out<=4'b0000;
        endcase
    end
endmodule

34.A 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.

// 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=2'b00;
            4'b0001:pos=2'b00;
            4'b0010:pos=2'b01;
            4'b0011:pos=2'b00;
            4'b0100:pos=2'b10;
            4'b0101:pos=2'b00;
            4'b0110:pos=2'b01;
            4'b0111:pos=2'b00;
            4'b1000:pos=2'b11;
            4'b1001:pos=2'b00;
            4'b1010:pos=2'b01;
            4'b1011:pos=2'b00;
            4'b1100:pos=2'b10;
            4'b1101:pos=2'b00;
            4'b1110:pos=2'b01;
            4'b1111:pos=2'b00;
        endcase
    end
endmodule

/*
always @(*) begin casez (in[3:0]) 4'bzzz1: out = 0; // in[3:1] can be anything 4'bzz1z: out = 1; 4'bz1zz: out = 2; 4'b1zzz: out = 3; default: out = 0; endcase end
*/

35.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.

// 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'bzzzzzz1z: pos=1;
            8'bzzzzz1zz: pos=2;
            8'bzzzz1zzz: pos=3;
            8'bzzz1zzzz: pos=4;
            8'bzz1zzzzz: pos=5;
            8'bz1zzzzzz: pos=6;
            8'b1zzzzzzz: pos=7;
            default: pos=0;
        endcase
    end
endmodule

36.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.

Scancode [15:0]Arrow key
16'he06b left arrow
16'he072 down arrow
16'he074 right arrow
16'he075 up arrow
Anything else none
// 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: ;
        endcase
    end
endmodule

37.Given four unsigned numbers, find the minimum. Unsigned numbers can be compared with standard comparison operators (a < b). Use the conditional operator to make two-way min circuits, then compose a few of them to create a 4-way min circuit. You'll probably want some wire vectors for the intermediate results.       Expected solution length: Around 5 lines.

module top_module (
    input [7:0] a, b, c, d,
    output [7:0] min);//
    wire [7:0] minab,mincd;
    assign minab=(a>b)?b:a;
    assign mincd=(c>d)?d:c;
    assign min=(minab>mincd)?mincd:minab;
    // assign intermediate_result1 = compare? true: false;
endmodule

38.Parity checking is often used as a simple method of detecting errors when transmitting data through an imperfect channel. Create a circuit that will compute a parity bit for a 8-bit byte (which will add a 9th bit to the byte). We will use "even" parity, where the parity bit is just the XOR of all 8 data bits.

module top_module (
    input [7:0] in,
    output parity); 
    assign parity = ^ in[7:0];
endmodule

39.Build a combinational circuit with 100 inputs, in[99:0].

There are 3 outputs:

  • out_and: output of a 100-input AND gate.
  • out_or: output of a 100-input OR gate.
  • out_xor: output of a 100-input XOR gate.
module top_module( 
    input [99:0] in,
    output out_and,
    output out_or,
    output out_xor 
);
    assign out_and = & in[99:0];
    assign out_or = | in[99:0];
    assign out_xor = ^ in[99:0];
endmodule

40.Given a 100-bit input vector [99:0], reverse its bit ordering.

module top_module( 
    input [99:0] in,
    output [99:0] out
);
    always@(*)
        begin
            for (integer i=0;i<100;i=i+1)
                out[i]=in[99-i];
        end
endmodule

41.A "population count" circuit counts the number of '1's in an input vector. Build a population count circuit for a 255-bit input vector.

module top_module( 
    input [254:0] in,
    output [7:0] out );
    always@(*)
        begin
            out=0;
            for (integer i=0;i<255;i=i+1)
                if (in[i])
                    out=out+1;
                else
                     ;   
        end
endmodule
//Warning (10230): Verilog HDL assignment warning at top_module.v(9): 
//truncated value with size 32 to match size of target (8)
//答案 module top_module ( input [254:0] in, output reg [7:0] out ); always @(*) begin // Combinational always block out = 0; for (int i=0;i<255;i++) out = out + in[i]; end endmodule

42.Create a 100-bit binary ripple-carry adder by instantiating 100 full adders. The adder adds two 100-bit numbers and a carry-in to produce a 100-bit sum and carry out. To encourage you to actually instantiate full adders, also output the carry-out from each full adder in the ripple-carry adder. cout[99] is the final carry-out from the last full adder, and is the carry-out you usually see.

module top_module( 
    input [99:0] a, b,
    input cin,
    output [99:0] cout,
    output [99:0] sum );
    assign cout[0] = a[0] & b[0] | a[0] & cin | b[0] & cin;
    assign sum[0]  = a[0] ^ b[0] ^ cin;

    
    integer i;
    
    always @ (*) begin
        for (i=1; i<100; i++) begin
            cout[i] = a[i] & b[i] | a[i] & cout[i-1] | b[i] & cout[i-1];
            sum[i]  = a[i] ^ b[i] ^ cout[i-1];
        end
    end
endmodule
//There are many full adders to instantiate. An instance array or generate statement would help here.
//这应该不是题目要求的解法

43.You are provided with a BCD one-digit adder named bcd_fadd that adds two BCD digits and carry-in, and produces a sum and carry-out.

module bcd_fadd {
    input [3:0] a,
    input [3:0] b,
    input     cin,
    output   cout,
    output [3:0] sum );

Instantiate 100 copies of bcd_fadd to create a 100-digit BCD ripple-carry adder. Your adder should add two 100-digit BCD numbers (packed into 400-bit vectors) and a carry-in to produce a 100-digit sum and carry out.

module top_module( 
    input [399:0] a, b,
    input cin,
    output cout,
    output [399:0] sum );
    wire [99:0] ccout;
    bcd_fadd inst1 (a[3:0],b[3:0],cin,ccout[0],sum[3:0]);
    genvar i;
    generate
        for (i=1;i<100;i++)
            begin : label
                bcd_fadd fadd (a[4*i+3:4*i],b[4*i+3:4*i],ccout[i-1],ccout[i],sum[4*i+3:4*i]);
            end
    endgenerate
    assign cout=ccout[99];
endmodule
//
//Warning (10230): Verilog HDL assignment warning at tb_modules.sv(8): truncated value with size 32 to match size 
//of target (4) File: /var/www/verilog/work/vlgSZma3E_dir/tb_modules.sv Line: 8

//GITHUB的答案
module top_module( 
    input [399:0] a, b,
    input cin,
    output cout,
    output [399:0] sum );
    
    wire [399:0] cout_tmp;
    bcd_fadd fadd(.a(a[3:0]), .b(b[3:0]), .cin(cin), .cout(cout_tmp[0]),.sum(sum[3:0]));
    assign cout = cout_tmp[396];
    
    generate
        genvar i;
        for(i = 4; i < 400; i=i+4) begin : adder
            bcd_fadd fadd(.a(a[i+3:i]), .b(b[i+3:i]), .cin(cout_tmp[i-4]), .cout(cout_tmp[i]),.sum(sum[i+3:i]));
        end
    endgenerate

endmodule

 

posted @ 2020-06-05 09:42  Kraken  阅读(8580)  评论(0编辑  收藏  举报