【hdlbits】个人学习交流分享(带答案)——Reading Simulations和Writing Testbenches部分

hdlbits网站:HDLBits (01xz.net)

其他hdlbits博客:

【hdlbits】个人学习交流分享(带答案)——verilog language部分-CSDN博客

【hdlbits】个人学习交流分享(带答案)——combinational logic部分-CSDN博客

【hdlbits】个人学习交流分享(带答案)——sequential logic部分-CSDN博客

【hdlbits】个人学习交流分享(带答案)——finite state machines(FSM)-CSDN博客

正文:

Verification: Reading Simulations

Finding bugs in code

Mux

要8 位宽的 2 对 1 多路复用器

原代码:

module top_module (
    input sel,
    input [7:0] a,
    input [7:0] b,
    output out  );

    assign out = (~sel & a) | (sel & b);

endmodule

问题:1.out位宽为1位,应该改成8位。

2.sel是1位,和8位的a/b进行&运算只会得到1位结果

正确答案:

module top_module (
    input sel,
    input [7:0] a,
    input [7:0] b,
    output [7:0]out  );

    assign out = ({8{sel}} & a) | (~{8{sel}} & b);

endmodule

NAND

题目给的5输入AND门

module andgate ( output out, input a, input b, input c, input d, input e );

原代码:

module top_module (input a, input b, input c, output out);//

    andgate inst1 ( a,b,c,out);

endmodule

问题:1.用5 输入 AND 门实现3输入NAND门,没有给d和e分配信号

2.另外接口排列out位置也不对

3.也没有体现出NAND门的效果

正确答案:

module top_module (input a, input b, input c, output out);//
    wire out1;
    andgate inst1 (out1,a,b,c,1'b1,1'b1);
    assign out=~out1;
endmodule

Mux

 要求实现4 对 1 多路复用器,提供了如下8位宽 2 对 1 多路复用器:

module mux2 (
    input sel,
    input [7:0] a,
    input [7:0] b,
    output [7:0] out
);

原代码:

module top_module (
    input [1:0] sel,
    input [7:0] a,
    input [7:0] b,
    input [7:0] c,
    input [7:0] d,
    output [7:0] out  ); //

    wire mux0, mux1;
    mux2 mux0 ( sel[0],    a,    b, mux0 );
    mux2 mux1 ( sel[1],    c,    d, mux1 );
    mux2 mux2 ( sel[1], mux0, mux1,  out );

endmodule

问题:1.wire位宽不对,应该是8位

2.例化名与模块名(mux2)重复了,语法错误

3.例化名与变量名(mux0和mux1)重复了,语法错误

4.sel信号配置错误,无法选出c信号。

mux2中要选mux1赋给out要求sel[1]为0,这时mux1中只能选d赋给mux1,可以实现“d→mux1→out”,无法实现“c→mux1→out”,也就是无法片选出c信号

正确答案:

module top_module (
    input [1:0] sel,
    input [7:0] a,
    input [7:0] b,
    input [7:0] c,
    input [7:0] d,
    output [7:0] out  ); //
 
    wire [7:0]  mux0, mux1;
    mux2 mux0_inst ( sel[0],    a,    b, mux0 );
    mux2 mux1_inst ( sel[0],    c,    d, mux1 );
    mux2 mux2_inst ( sel[1], mux0, mux1,  out );

endmodule

add/sub

原代码:

// synthesis verilog_input_version verilog_2001
module top_module ( 
    input do_sub,
    input [7:0] a,
    input [7:0] b,
    output reg [7:0] out,
    output reg result_is_zero
);//

    always @(*) begin
        case (do_sub)
          0: out = a+b;
          1: out = a-b;
        endcase

        if (~out)
            result_is_zero = 1;
    end

endmodule

问题:1.if-else语句不完整缺少else,出现了未设定的状态,进行综合会出现latch

2.if内的(~out)是对out结果按位取反,这混淆逻辑非和按位非,出现错误。

举一个例子理解:

out是8'b10001000,~out就是8'b01110111,if的()内进行的是布尔值的判断,这里~out的布尔值为true(逻辑1),所以会执行“result_is_zero = 1;”这一句,即认定out为0是真。这显然是错误的。

布尔值的判断应该用逻辑非!out,只有out是8'b00000000时候,也就是只有out为0时候,!out才为ture(逻辑1),才会执行“result_is_zero = 1;”这一句,即认定out为0是真。

虽然在很多情况下“逻辑与或非”和‘‘按位与或非’’都仿真综合得到正确的结果,但是这并不适用于所有情况,两者并不完全等价,所以要能够区分“逻辑与或非”和‘‘按位与或非’’

可以参考:逻辑运算与按位运算_按位逻辑与运算-CSDN博客

按位运算符、逻辑运算符_两个数的逻辑运算和按位运算-CSDN博客

正确答案:

// synthesis verilog_input_version verilog_2001
module top_module ( 
    input do_sub,
    input [7:0] a,
    input [7:0] b,
    output reg [7:0] out,
    output reg result_is_zero
);//

    always @(*) begin
        case (do_sub)
          0: out = a+b;
          1: out = a-b;
        endcase

        if (!out)
            result_is_zero = 1;
        else
        	result_is_zero = 0;
    end

endmodule

case statement

原代码

module top_module (
    input [7:0] code,
    output reg [3:0] out,
    output reg valid=1 );//

     always @(*)
        case (code)
            8'h45: out = 0;
            8'h16: out = 1;
            8'h1e: out = 2;
            8'd26: out = 3;
            8'h25: out = 4;
            8'h2e: out = 5;
            8'h36: out = 6;
            8'h3d: out = 7;
            8'h3e: out = 8;
            6'h46: out = 9;
            default: valid = 0;
        endcase

endmodule

问题:1.vaild赋初值的位置错误,在变量声明的括号内不会起作用,想要赋初值在always块内起作用,应该把赋值语句放always块内。

2.把8'd26改为8'h26,6'h46改为8'h46

3.没有给out分配默认值,default下应该给out赋值(按理说这里随便赋都可以,我赋值为4'hf,结果仿真不对,核对了时序图作者这里要求default下必须把out赋值为0,再次吐槽作者项目要求都提不清楚)

module top_module (
    input [7:0] code,
    output reg [3:0] out,
    output reg valid );//

    always @(*)begin
        valid=1;
        case (code)
            8'h45: out = 4'h0;
            8'h16: out = 4'h1;
            8'h1e: out = 4'h2;
            8'h26: out = 4'h3;
            8'h25: out = 4'h4;
            8'h2e: out = 4'h5;
            8'h36: out = 4'h6;
            8'h3d: out = 4'h7;
            8'h3e: out = 4'h8;
            8'h46: out = 4'h9;
            default:begin
                valid=0;
                out=4'h0;
            end
        endcase
    end
endmodule

buliding a circuit from a simulation waveform

combinational circuit 1

组合电路可以根据波形图写真值表或者写逻辑表达式,没难度,直接放答案,下面题目同

module top_module (
    input a,
    input b,
    output q );//

    assign q = a&b; // Fix me

endmodule

combinational circuit 2

module top_module (
    input a,
    input b,
    input c,
    input d,
    output q );//

    assign q =~a & ~b & ~c & ~d | ~a & ~b & c & d | ~a & b & ~c & d | ~a & b & c & ~d | a & ~b & ~c & d | a & ~b & c & ~d | a & b & ~c & ~d | a & b & c & d;  // Fix me

endmodule

combinational circuit 3

module top_module (
    input a,
    input b,
    input c,
    input d,
    output q );//

    assign q = b & d | b & c | a & d | a & c; // Fix me

endmodule

combinational circuit 4

module top_module (
    input a,
    input b,
    input c,
    input d,
    output q );//

    assign q =b | c;// Fix me

endmodule

combinational circuit 5

根据仿真波形图很容易看出这是多路选择器,c是选择端,a、b、d、e是数据端,q是输出端

module top_module (
    input [3:0] a,
    input [3:0] b,
    input [3:0] c,
    input [3:0] d,
    input [3:0] e,
    output [3:0] q );
    always @(*) begin
        case(c)
            4'd0:	q = b;
            4'd1:	q = e;
            4'd2:	q = a;
            4'd3:	q = d;
            default:q = 4'hf;
        endcase
    end
endmodule

combinational circuit 6

本题也是多路选择器,a是选择端,q是输出端,没有给出数据端

module top_module (
    input [2:0] a,
    output [15:0] q ); 
    always @(*) begin
        case(a)
            3'd0:	q = 16'h1232;
            3'd1:	q = 16'haee0;
            3'd2:	q = 16'h27d4;
            3'd3:	q = 16'h5a0e;
            3'd4:	q = 16'h2066;
            3'd5:	q = 16'h64ce;
            3'd6:	q = 16'hc526;
            default:q = 16'h2f19;
        endcase
    end
endmodule

sequential circuit 7

module top_module (
    input clk,
    input a,
    output reg q );
    always @(posedge clk) begin
        q <= ~a;
    end
endmodule

sequential circuit 8

当clock为1,p波形和a相同;clock为0,p和上一个clk的p一样,保持不变。

当clock下降沿时候,q的数值同q,注意的是,下降沿出现的clk内,q数值就和变到p相同了,这里没有一个clk的时延,所以赋值要用阻塞赋值。

module top_module (
    input clock,
    input a,
    output p,
    output q );
    assign p = clock ? a : p;
    
    always @(negedge clock) begin
        q = p;//看波形,下降沿出现的clk,q数值就和变到p相同了,没有时延,所以是阻塞赋值“=”。
    end
endmodule

sequential circuit 9

本题是一个6禁止计数器,a是置数信号,置数置为4。

module top_module (
    input clk,
    input a,
    output reg [3:0] q );
    always @(posedge clk) begin
        if(a) begin
            q <= 4'd4;
        end
        else if(q == 4'd6) begin
            q <= 4'd0;
        end
        else begin
            q <= q + 4'd1;
        end
    end
endmodule

sequential circuit 10

module top_module (
    input clk,
    input a,
    input b,
    output q,
    output reg state  );
    assign q = a^b^state;
    always @(posedge clk) begin
	    if (a&b) begin
		    state <= 'd1;
	    end
	    else if (~a&~b) begin
		    state <= 'd0;
	    end
	    else begin
		    state <= state;
	    end
    end
endmodule

verification:writing testbenches

clock 

提供模块:module dut ( input clk ) ;

module top_module ( );
    
    reg clk;
    dut ut(clk);
    initial begin
        clk = 1'b0;
    end
    always begin
        #5 clk = ~clk;        
    end
        
endmodule

testbench 1

module top_module ( output reg A, output reg B );//

    // generate input patterns here
    initial begin
        A = 1'b0;
        B = 1'b0;
        #10 A = 1'b1;
        #5 B = 1'b1;
        #5 A = 1'b0;
        #20 B = 1'b0;
    end

endmodule

把A和B分开写更清楚:

module top_module ( output reg A, output reg B );//

    // generate input patterns here
    initial begin
        A = 1'b0;
        #10 A = 1'b1;
        #10 A = 1'b0;
    end
    
     initial begin
        B = 1'b0;
        #15 B = 1'b1;
        #25 B = 1'b0;
    end

endmodule

AND gate

提供的AND模块:

module andgate (
    input [1:0] in,
    output out
);

module top_module();

    reg [1:0]in;
    reg out;
    
    andgate u0(in,out);
    
    initial begin
        in[0] = 1'b0;
        in[1] = 1'b0;
        #10 in[0] = 1'b1;
        #10 
        in[0] = 1'b0;
        in[1] = 1'b1;
        #10 in[0] = 1'b1;
    end
        
endmodule

testbench 2

提供的模块:

module q7 (
    input clk,
    input in,
    input [2:0] s,
    output out
);

module top_module();
    reg clk,in,out;
    reg [2:0]s;
    
    q7 ut(clk,in,s,out);
    
    initial begin
        in=1'b0;
        #20 in=1'b1;
        #10 in=1'b0;
        #10 in=1'b1;
        #30 in=1'b0;
    end
    
    initial begin
        s=3'd2;
        #10 s=3'd6;
        #10 s=3'd2;
        #10 s=3'd7;
        #10 s=3'd0;
    end
    
    initial begin
        clk=0;
    end
    
    always begin
        #5 clk=~clk;
    end

endmodule

T filp-flop

提供的T触发器模块:

module tff (
    input clk,
    input reset,   // active-high synchronous reset
    input t,       // toggle
    output q
);
module top_module ();
    reg clk,reset,t,q;
    
    tff ut(clk,reset,t,q);
    
    initial begin
        reset=1'd0;
        #10 reset=1'd1;
        #10 reset=1'd0; 
    end
    
    always@(posedge clk)begin
        if(reset)//题干表述,复位reset将toggle(t)置0,复位信号无效后将t置1;
            t<=1'd0;
        else
            t<=1'd1;
    end
    
    initial begin
        clk=0;
    end
    
    always begin
        #5 clk=~clk;
    end

endmodule

到这里hdlbits总共178道题目练习就彻底结束了,如果能吃透这178道题,也算是对verilog HDL基础有了不错的了解,算是为FPGA开发和数字IC设计打了HDL 的基础

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值