HDLBits-Verilog Practice-3-Verification: Reading Simulations -> Verification: Writing Testbenches

注:建议使用 Ctrl+F 利用关键词、题号、题目名称 查阅本文内容

笔记内容

  1. 本文范围 Verification: Reading Simulations -> Verification: Writing Testbenches

  2. 网页本身给出的语法点,和一些语法的使用思路

  3. 做题过程中的反思

  4. 参考HDLBits 中文导学 - 知乎

  5. 参考答案xiaop1/Verilog-Practice: HDLBits website practices & solutions

Verification: Reading Simulations

Finding bugs in code

Bugs mux2

  1. A mux coded as (~sel & a) | (sel & b) does not work for vectors.
    This is because these are bitwise operators, and sel is only a 1 bit wide quantity, which leaves the upper bits of a and b zeroed. It is possible to code it using the replication operator, but this is somewhat difficult to read: ( {8{~sel}} & a ) | ( {8{sel}} & b )

  2. The simulation waveform shows that when sel = 1, a should be selected. This is flipped in the suggested code.

    因此,我们有, assign out = sel ? a : b;

Bugs nand3

You must use the provided 5-input AND gate:module andgate ( output out, input a, input b, input c, input d, input e );

管脚若悬空(dangling)则默认置零,因此末两个空闲输入需显式指明为 1'b1

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

endmodule

Bugs mux4

  1. 声明临时向量时记得要写向量域
  2. 这里使用 分治算法 解决 选择 问题,需要分析 选择的依据(喂给子模块的sel)的选取 。
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 mux00 ( sel[0],    a,    b, mux0 );
mux2 mux01 ( sel[0],    c,    d, mux1 );
mux2 mux02 ( sel[1], mux0, mux1,  out );

endmodule

Bugs addsubz

  1. 对于向量是否为全0 应先使用 归约运算符 得到 1-bit 的结果;再写判断
  2. 组合逻辑 if-else 要写全避免锁存器;
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

Bugs case

错误的代码:

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

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

always块 里的 case语句中的 default 对valid 的赋值(L19) 将会永久覆盖 上面module参数声明列表中的默认赋值(L4)。即,上述代码将 valid 恒置为0。

因此,如下面代码所示,在**always块内case块外 (L10) **增加关于valid的默认赋值。

(由此看来,在参数列表的默认赋值没什么用,太容易被覆盖了。)

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

	// A combinational always block.
	always @(*) begin
		out = 0;		// To avoid latches, give the outputs a default assignment
		valid = 1;		//   then override them in the case statement. This is less
						//   code than assigning a value to every variable for every case.
		case (code)
			8'h45: out = 0;
			8'h16: out = 1;
			8'h1e: out = 2;
			8'h26: out = 3;		// 8'd26 is 8'h1a
			8'h25: out = 4;
			8'h2e: out = 5;
			8'h36: out = 6;
			8'h3d: out = 7;
			8'h3e: out = 8;
			8'h46: out = 9;		// 6'h46 is 8'h46
			default: valid = 0;
		endcase
	end
	
endmodule

Build a circuit from a simulation waveform.

笔记

Sim/circuit9

在模块的输入输出声明处,可以初始化输出值(代码 L25)。

同步复位值在代码L29处控制。

以上是两件事,不可随意互相取代。

module_port_initialization

相应代码

module top_module ();
	reg clk=0;
	always #5 clk = ~clk;  // Create clock with period=10
	initial `probe_start;   // Start the timing diagram

	`probe(clk);        // Probe signal "clk"
    `probe(a); 
    `probe(q); 
	
    // A testbench
	reg in=0;
    reg a=1;
	initial begin
		#40 a<=0;
		#50 $finish;            // Quit the simulation
	end
    reg [3:0]q;
    test inst1 ( clk,a,q );   // Sub-modules work too.

endmodule

module test (
    input clk,
    input a,
    output reg [3:0] q=4'h3 );	//initialization
    
    always@(posedge clk)
        if(a)
            q<=4'h4;
        else 
            q<= (q+1'b1==4'h7)? 4'h0:q+1'b1;
            
endmodule

Sim/circuit8

本题的p本质是一个锁存器,其波形图一定程度上展示了锁存器的毛刺敏感。

波形图

Simcircuit8_wavedrom

代码

assign p=clock?a&clock:p;   

always@(negedge clock)
	q<=p|clock;

Verification: Writing Testbenches

Tb/and

这题第五个测试样例要求保持第四个样例的输出不变= =。就是在这里记录一下这个坑。(因为它的输出不显示第五个测试样例,无法做针对性修改。)

initial begin
  in = 2'b00;
  #10
  in = 2'b01;
  #10
  in = 2'b10;
  #10
  in = 2'b11;
end

andgate inst(.in(in), .out(out));
posted @ 2022-10-12 16:36  yx21  阅读(78)  评论(0编辑  收藏  举报