No submissions yet

Submit your solution to display here.

Please login/signup to submit your solution.

Testbench Code

`timescale 1ns/1ps
module tb_pwm4_basic;
  reg        clk;
  reg        rst;
  reg  [3:0] duty;

  wire       pwm_out;
  wire       expected_pwm;
  wire       mismatch;

  pwm4_basic dut(.clk(clk), .rst(rst), .duty(duty), .pwm_out(pwm_out));

  reg [3:0] exp_cnt;
  reg       exp_pwm_q;
  assign expected_pwm = exp_pwm_q;

  always @(posedge clk) begin
    exp_pwm_q <= rst ? 1'b0 : (exp_cnt < duty);
    exp_cnt   <= rst ? 4'd0 : (exp_cnt + 4'd1);
  end

  assign mismatch = (pwm_out !== expected_pwm);

  initial begin
    clk = 1'b0;
    forever #5 clk = ~clk;
  end

  initial begin
    $dumpfile("tb_pwm4_basic.vcd");
    $dumpvars(0, clk, rst, duty, pwm_out, expected_pwm, mismatch);
  end

  integer TOTAL_TEST_CASES, TOTAL_PASSED_TEST_CASES, TOTAL_FAILED_TEST_CASES;

  task apply_cycles;
    input integer n; integer i;
    begin for (i=0;i<n;i=i+1) @(posedge clk); end
  endtask

  task run_frame_now;
    input [3:0] val;
    input [8*40-1:0] name;
    integer i, highs; reg case_failed;
    begin
      duty = val;
      highs = 0; case_failed = 0;
      for (i=0;i<16;i=i+1) begin
        @(posedge clk);
        if (expected_pwm === 1'b1) highs = highs + 1;
        if (mismatch) case_failed = 1;
      end
      $display("CASE=%s : duty=%0d highs=%0d expected_highs=%0d %s",
               name, val, highs, val, case_failed ? "MISMATCH" : "OK");
      TOTAL_TEST_CASES = TOTAL_TEST_CASES + 1;
      if (!case_failed && highs==val) TOTAL_PASSED_TEST_CASES = TOTAL_PASSED_TEST_CASES + 1;
      else TOTAL_FAILED_TEST_CASES = TOTAL_FAILED_TEST_CASES + 1;
    end
  endtask

  task run_frame_next;
    input [3:0] val;
    input [8*40-1:0] name;
    integer i, highs; reg case_failed;
    begin
      @(negedge clk); duty = val;
      highs = 0; case_failed = 0;
      for (i=0;i<16;i=i+1) begin
        @(posedge clk);
        if (expected_pwm === 1'b1) highs = highs + 1;
        if (mismatch) case_failed = 1;
      end
      $display("CASE=%s : duty=%0d highs=%0d expected_highs=%0d %s",
               name, val, highs, val, case_failed ? "MISMATCH" : "OK");
      TOTAL_TEST_CASES = TOTAL_TEST_CASES + 1;
      if (!case_failed && highs==val) TOTAL_PASSED_TEST_CASES = TOTAL_PASSED_TEST_CASES + 1;
      else TOTAL_FAILED_TEST_CASES = TOTAL_FAILED_TEST_CASES + 1;
    end
  endtask

  initial begin
    TOTAL_TEST_CASES = 0; TOTAL_PASSED_TEST_CASES = 0; TOTAL_FAILED_TEST_CASES = 0;

    rst = 1'b1; duty = 4'd0; apply_cycles(4);
    @(negedge clk) rst = 1'b0;

    run_frame_now (4'd0 , "duty_0_percent");
    run_frame_next(4'd1 , "duty_min_nonzero");
    run_frame_next(4'd4 , "duty_25_percent");
    run_frame_next(4'd8 , "duty_50_percent");
    run_frame_next(4'd12, "duty_75_percent_minus");
    run_frame_next(4'd15, "duty_max");

    $display("TOTAL_TEST_CASES=%0d",        TOTAL_TEST_CASES);
    $display("TOTAL_PASSED_TEST_CASES=%0d", TOTAL_PASSED_TEST_CASES);
    $display("TOTAL_FAILED_TEST_CASES=%0d", TOTAL_FAILED_TEST_CASES);
    $display("ALL_TEST_CASES_PASSED=%s",    (TOTAL_FAILED_TEST_CASES==0) ? "true" : "false");
    $finish;
  end
endmodule