prompt:
module top_module (
	input [2:0] a,
	output reg [15:0] q
);

test:
`timescale 1 ps/1 ps
`define OK 12
`define INCORRECT 13
module reference_module (
	input [2:0] a,
	output reg [15:0] q
);

	always @(*)
		case (a)
			0: q = 4658;
			1: q = 44768;
			2: q = 10196;
			3: q = 23054;
			4: q = 8294;
			5: q = 25806;
			6: q = 50470;
			7: q = 12057;
		endcase

endmodule

module stimulus_gen (
	input clk,
	output logic [2:0] a,
	output reg[511:0] wavedrom_title,
	output reg wavedrom_enable
);

// Add two ports to module stimulus_gen:
//    output [511:0] wavedrom_title
//    output reg wavedrom_enable

	task wavedrom_start(input[511:0] title = "");
	endtask

	task wavedrom_stop;
		#1;
	endtask

	initial begin
		@(negedge clk) wavedrom_start("Unknown circuit");
			@(posedge clk) {a} <= 0;
			repeat(10) @(posedge clk,negedge clk) a <= a + 1;
		wavedrom_stop();

		repeat(100) @(posedge clk, negedge clk)
			a <= $urandom;
		$finish;
	end

endmodule

module tb();

	typedef struct packed {
		int errors;
		int errortime;
		int errors_q;
		int errortime_q;

		int clocks;
	} stats;

	stats stats1;

	wire[511:0] wavedrom_title;
	wire wavedrom_enable;
	int wavedrom_hide_after_time;

	reg clk=0;
	initial forever
		#5 clk = ~clk;

	logic [2:0] a;
	logic [15:0] q_ref;
	logic [15:0] q_dut;

	initial begin
		$dumpfile("wave.vcd");
		$dumpvars(1, stim1.clk, tb_mismatch ,a,q_ref,q_dut );
	end

	wire tb_match;		// Verification
	wire tb_mismatch = ~tb_match;

	stimulus_gen stim1 (
		.clk,
		.* ,
		.a );
	reference_module good1 (
		.a,
		.q(q_ref) );

	top_module top_module1 (
		.a,
		.q(q_dut) );

	bit strobe = 0;
	task wait_for_end_of_timestep;
		repeat(5) begin
			strobe <= !strobe;  // Try to delay until the very end of the time step.
			@(strobe);
		end
	endtask

	final begin
		if (stats1.errors_q) $display("Hint: Output '%s' has %0d mismatches. First mismatch occurred at time %0d.", "q", stats1.errors_q, stats1.errortime_q);
		else $display("Hint: Output '%s' has no mismatches.", "q");

		$display("Hint: Total mismatched samples is %1d out of %1d samples\n", stats1.errors, stats1.clocks);
		$display("Simulation finished at %0d ps", $time);
		$display("Mismatches: %1d in %1d samples", stats1.errors, stats1.clocks);
	end

	// Verification: XORs on the right makes any X in good_vector match anything, but X in dut_vector will only match X.
	assign tb_match = ( { q_ref } === ( { q_ref } ^ { q_dut } ^ { q_ref } ) );
	// Use explicit sensitivity list here. @(*) causes NetProc::nex_input() to be called when trying to compute
	// the sensitivity list of the @(strobe) process, which isn't implemented.
	always @(posedge clk, negedge clk) begin

		stats1.clocks++;
		if (!tb_match) begin
			if (stats1.errors == 0) stats1.errortime = $time;
			stats1.errors++;
		end
		if (q_ref !== ( q_ref ^ q_dut ^ q_ref ))
		begin if (stats1.errors_q == 0) stats1.errortime_q = $time;
			stats1.errors_q = stats1.errors_q+1'b1; end

	end
endmodule

detail_description:
This is a combinational circuit. Read the simulation waveforms to determine what the circuit does, then implement it.

// time            a                  q
// 0ns             x                  x
// 5ns             x                  x
// 10ns            x                  x
// 15ns            0               1232
// 20ns            1               aee0
// 25ns            2               27d4
// 30ns            3               5a0e
// 35ns            4               2066
// 40ns            5               64ce
// 45ns            6               c526
// 50ns            7               2f19
// 55ns            0               1232
// 60ns            1               aee0
// 65ns            2               27d4
// 70ns            4               2066
// 75ns            1               aee0
// 80ns            1               aee0
// 85ns            3               5a0e
// 90ns            5               64ce


prompt:
module top_module (
	input clk,
	input areset,
	input bump_left,
	input bump_right,
	input ground,
	input dig,
	output walk_left,
	output walk_right,
	output aaah,
	output digging
);

test:
`timescale 1 ps/1 ps
`define OK 12
`define INCORRECT 13
module reference_module (
	input clk,
	input areset,
	input bump_left,
	input bump_right,
	input ground,
	input dig,
	output walk_left,
	output walk_right,
	output aaah,
	output digging
);
	parameter WL=0, WR=1, FALLL=2, FALLR=3, DIGL=4, DIGR=5, DEAD=6;
	reg [2:0] state;
	reg [2:0] next;

    reg [4:0] fall_counter;

    always_comb begin
		case (state)
			WL: if (!ground) next = FALLL;
				else if (dig) next = DIGL;
				else if (bump_left) next = WR;
				else next = WL;
			WR:
				if (!ground) next = FALLR;
				else if (dig) next = DIGR;
				else if (bump_right) next = WL;
				else next = WR;
			FALLL: next = ground ? (fall_counter >= 20 ? DEAD : WL) : FALLL;
			FALLR: next = ground ? (fall_counter >= 20 ? DEAD : WR) : FALLR;
			DIGL: next = ground ? DIGL : FALLL;
			DIGR: next = ground ? DIGR : FALLR;
			DEAD: next = DEAD;
		endcase
    end

    always @(posedge clk, posedge areset) begin
		if (areset) state <= WL;
        else state <= next;
	end

	always @(posedge clk) begin
		if (state == FALLL || state == FALLR) begin
			if (fall_counter < 20)
				fall_counter <= fall_counter + 1'b1;
		end
		else
			fall_counter <= 0;
	end

	assign walk_left = (state==WL);
	assign walk_right = (state==WR);
	assign aaah = (state == FALLL) || (state == FALLR);
	assign digging = (state == DIGL) || (state == DIGR);

endmodule

module stimulus_gen (
	input clk,
	output logic areset,
	output logic bump_left,
	output logic bump_right,
	output logic dig,
	output logic ground,
	output reg[511:0] wavedrom_title,
	output reg wavedrom_enable,
	input tb_match
);

	reg reset;
	assign areset = reset;

	task reset_test(input async=0);
		bit arfail, srfail, datafail;

		@(posedge clk);
		@(posedge clk) reset <= 0;
		repeat(3) @(posedge clk);

		@(negedge clk) begin datafail = !tb_match ; reset <= 1; end
		@(posedge clk) arfail = !tb_match;
		@(posedge clk) begin
			srfail = !tb_match;
			reset <= 0;
		end
		if (srfail)
			$display("Hint: Your reset doesn't seem to be working.");
		else if (arfail && (async || !datafail))
			$display("Hint: Your reset should be %0s, but doesn't appear to be.", async ? "asynchronous" : "synchronous");
		// Don't warn about synchronous reset if the half-cycle before is already wrong. It's more likely
		// a functionality error than the reset being implemented asynchronously.

	endtask

// Add two ports to module stimulus_gen:
//    output [511:0] wavedrom_title
//    output reg wavedrom_enable

	task wavedrom_start(input[511:0] title = "");
	endtask

	task wavedrom_stop;
		#1;
	endtask

	initial begin
		reset <= 1'b1;
		@(posedge clk);
		reset <= 0;
		{bump_left, bump_right, ground, dig} <= 2;
		repeat(2) @(posedge clk);
		{bump_left, bump_right, ground, dig} <= 3;
		@(posedge clk);
		{bump_left, bump_right, ground, dig} <= 2;
		@(posedge clk);
		{bump_left, bump_right, ground, dig} <= 10;
		@(posedge clk);
		{bump_left, bump_right, ground, dig} <= 2;
		@(posedge clk);
		{bump_left, bump_right, ground, dig} <= 0;
		repeat(3) @(posedge clk);
		{bump_left, bump_right, ground, dig} <= 3;
		@(posedge clk);
		{bump_left, bump_right, ground, dig} <= 2;
		repeat(4) @(posedge clk);

		{bump_left, bump_right, ground, dig} <= 0;		// Fall
		repeat(20) @(posedge clk);
		{bump_left, bump_right, ground, dig} <= 2;		// Survive
		repeat(1) @(posedge clk);

		{bump_left, bump_right, ground, dig} <= 0;		// Fall
		repeat(21) @(posedge clk);
		{bump_left, bump_right, ground, dig} <= 2;		// Splat after falling left
		repeat(20) @(posedge clk) begin
			{dig, bump_right, bump_left} <= $random & $random;	// See if it's handled correctly.
			ground <= |($random & 7);
		end

		reset <= 1;
		{bump_left, bump_right, ground, dig} <= 2;		// Normal
		@(posedge clk)
		reset <= 0;		// Resurrect.
		bump_left <= 1;
		repeat(5) @(posedge clk);
		{bump_left, bump_right, ground, dig} <= 0;		// Fall
		repeat(21) @(posedge clk);
		{bump_left, bump_right, ground, dig} <= 2;		// Splat after falling right
		repeat(20) @(posedge clk) begin
			{dig, bump_right, bump_left} <= $random & $random;	// See if it's handled correctly.
			ground <= |($random & 7);
		end

		reset <= 1;
		@(posedge clk)
		reset <= 0;		// Resurrect.
		{bump_left, bump_right, ground, dig} <= 2;		// Normal
		wavedrom_start("Splat?");
		@(posedge clk);
		{bump_left, bump_right, ground, dig} <= 0;		// Fall
		repeat(24) @(posedge clk);
		{bump_left, bump_right, ground, dig} <= 2;		// Splat? (24-cycles)
		repeat(2) @(posedge clk);
		wavedrom_stop();

		reset <= 1;
		@(posedge clk)
		reset <= 0;		// Resurrect.
		{bump_left, bump_right, ground, dig} <= 2;		// Normal
		@(posedge clk);
		@(posedge clk);
		{bump_left, bump_right, ground, dig} <= 0;		// Fall
		repeat(35) @(posedge clk);
		{bump_left, bump_right, ground, dig} <= 2;		// Splat? (Test for 5-bit non-saturating counter)
		repeat(2) @(posedge clk);
		repeat(20) @(posedge clk) begin
			{dig, bump_right, bump_left} <= $random & $random;	// See if it's handled correctly.
			ground <= |($random & 7);
		end

		reset <= 1;
		{bump_left, bump_right, ground, dig} <= 2;		// Normal
		@(posedge clk);
		reset <= 0;		// Resurrect.
		@(posedge clk);
		{bump_left, bump_right, ground, dig} <= 0;		// Fall
		repeat(67) @(posedge clk);
		{bump_left, bump_right, ground, dig} <= 2;		// Splat? (Test for 6-bit non-saturating counter)
		repeat(20) @(posedge clk) begin
			{dig, bump_right, bump_left} <= $random & $random;	// See if it's handled correctly.
			ground <= |($random & 7);
		end

		reset <= 1;
		{bump_left, bump_right, ground, dig} <= 2;		// Normal
		@(posedge clk)
		reset <= 0;		// Resurrect.

		repeat(400) @(posedge clk, negedge clk) begin
			{dig, bump_right, bump_left} <= $random & $random;
			ground <= |($random & 7);
			reset <= !($random & 31);
		end

		#1 $finish;
	end

endmodule

module tb();

	typedef struct packed {
		int errors;
		int errortime;
		int errors_walk_left;
		int errortime_walk_left;
		int errors_walk_right;
		int errortime_walk_right;
		int errors_aaah;
		int errortime_aaah;
		int errors_digging;
		int errortime_digging;

		int clocks;
	} stats;

	stats stats1;

	wire[511:0] wavedrom_title;
	wire wavedrom_enable;
	int wavedrom_hide_after_time;

	reg clk=0;
	initial forever
		#5 clk = ~clk;

	logic areset;
	logic bump_left;
	logic bump_right;
	logic ground;
	logic dig;
	logic walk_left_ref;
	logic walk_left_dut;
	logic walk_right_ref;
	logic walk_right_dut;
	logic aaah_ref;
	logic aaah_dut;
	logic digging_ref;
	logic digging_dut;

	initial begin
		$dumpfile("wave.vcd");
		$dumpvars(1, stim1.clk, tb_mismatch ,clk,areset,bump_left,bump_right,ground,dig,walk_left_ref,walk_left_dut,walk_right_ref,walk_right_dut,aaah_ref,aaah_dut,digging_ref,digging_dut );
	end

	wire tb_match;		// Verification
	wire tb_mismatch = ~tb_match;

	stimulus_gen stim1 (
		.clk,
		.* ,
		.areset,
		.bump_left,
		.bump_right,
		.ground,
		.dig );
	reference_module good1 (
		.clk,
		.areset,
		.bump_left,
		.bump_right,
		.ground,
		.dig,
		.walk_left(walk_left_ref),
		.walk_right(walk_right_ref),
		.aaah(aaah_ref),
		.digging(digging_ref) );

	top_module top_module1 (
		.clk,
		.areset,
		.bump_left,
		.bump_right,
		.ground,
		.dig,
		.walk_left(walk_left_dut),
		.walk_right(walk_right_dut),
		.aaah(aaah_dut),
		.digging(digging_dut) );

	bit strobe = 0;
	task wait_for_end_of_timestep;
		repeat(5) begin
			strobe <= !strobe;  // Try to delay until the very end of the time step.
			@(strobe);
		end
	endtask

	final begin
		if (stats1.errors_walk_left) $display("Hint: Output '%s' has %0d mismatches. First mismatch occurred at time %0d.", "walk_left", stats1.errors_walk_left, stats1.errortime_walk_left);
		else $display("Hint: Output '%s' has no mismatches.", "walk_left");
		if (stats1.errors_walk_right) $display("Hint: Output '%s' has %0d mismatches. First mismatch occurred at time %0d.", "walk_right", stats1.errors_walk_right, stats1.errortime_walk_right);
		else $display("Hint: Output '%s' has no mismatches.", "walk_right");
		if (stats1.errors_aaah) $display("Hint: Output '%s' has %0d mismatches. First mismatch occurred at time %0d.", "aaah", stats1.errors_aaah, stats1.errortime_aaah);
		else $display("Hint: Output '%s' has no mismatches.", "aaah");
		if (stats1.errors_digging) $display("Hint: Output '%s' has %0d mismatches. First mismatch occurred at time %0d.", "digging", stats1.errors_digging, stats1.errortime_digging);
		else $display("Hint: Output '%s' has no mismatches.", "digging");

		$display("Hint: Total mismatched samples is %1d out of %1d samples\n", stats1.errors, stats1.clocks);
		$display("Simulation finished at %0d ps", $time);
		$display("Mismatches: %1d in %1d samples", stats1.errors, stats1.clocks);
	end

	// Verification: XORs on the right makes any X in good_vector match anything, but X in dut_vector will only match X.
	assign tb_match = ( { walk_left_ref, walk_right_ref, aaah_ref, digging_ref } === ( { walk_left_ref, walk_right_ref, aaah_ref, digging_ref } ^ { walk_left_dut, walk_right_dut, aaah_dut, digging_dut } ^ { walk_left_ref, walk_right_ref, aaah_ref, digging_ref } ) );
	// Use explicit sensitivity list here. @(*) causes NetProc::nex_input() to be called when trying to compute
	// the sensitivity list of the @(strobe) process, which isn't implemented.
	always @(posedge clk, negedge clk) begin

		stats1.clocks++;
		if (!tb_match) begin
			if (stats1.errors == 0) stats1.errortime = $time;
			stats1.errors++;
		end
		if (walk_left_ref !== ( walk_left_ref ^ walk_left_dut ^ walk_left_ref ))
		begin if (stats1.errors_walk_left == 0) stats1.errortime_walk_left = $time;
			stats1.errors_walk_left = stats1.errors_walk_left+1'b1; end
		if (walk_right_ref !== ( walk_right_ref ^ walk_right_dut ^ walk_right_ref ))
		begin if (stats1.errors_walk_right == 0) stats1.errortime_walk_right = $time;
			stats1.errors_walk_right = stats1.errors_walk_right+1'b1; end
		if (aaah_ref !== ( aaah_ref ^ aaah_dut ^ aaah_ref ))
		begin if (stats1.errors_aaah == 0) stats1.errortime_aaah = $time;
			stats1.errors_aaah = stats1.errors_aaah+1'b1; end
		if (digging_ref !== ( digging_ref ^ digging_dut ^ digging_ref ))
		begin if (stats1.errors_digging == 0) stats1.errortime_digging = $time;
			stats1.errors_digging = stats1.errors_digging+1'b1; end

	end
endmodule

detail_description:
The game Lemmings involves critters with fairly simple brains. So simple that we are going to model it using a finite state machine. In the Lemmings' 2D world, Lemmings can be in one of two states: walking left (walk_left is 1) or walking right (walk_right is 1). It will switch directions if it hits an obstacle. In particular, if a Lemming is bumped on the left (by receiving a 1 on bump_left), it will walk right. If it's bumped on the right (by receiving a 1 on bump_right), it will walk left. If it's bumped on both sides at the same time, it will still switch directions.
// In addition to walking left and right and changing direction when bumped, when ground=0, the Lemming will fall and say ""aaah!"". When the ground reappears (ground=1), the Lemming will resume walking in the same direction as before the fall. Being bumped while falling does not affect the walking direction, and being bumped in the same cycle as ground disappears (but not yet falling), or when the ground reappears while still falling, also does not affect the walking direction.
// In addition to walking and falling, Lemmings can sometimes be told to do useful things, like dig (it starts digging when dig=1). A Lemming can dig if it is currently walking on ground (ground=1 and not falling), and will continue digging until it reaches the other side (ground=0). At that point, since there is no ground, it will fall (aaah!), then continue walking in its original direction once it hits ground again. As with falling, being bumped while digging has no effect, and being told to dig when falling or when there is no ground is ignored. (In other words, a walking Lemming can fall, dig, or switch directions. If more than one of these conditions are satisfied, fall has higher precedence than dig, which has higher precedence than switching directions.)
// Although Lemmings can walk, fall, and dig, Lemmings aren't invulnerable. If a Lemming falls for too long then hits the ground, it can splatter. In particular, if a Lemming falls for more than 20 clock cycles then hits the ground, it will splatter and cease walking, falling, or digging (all 4 outputs become 0), forever (Or until the FSM gets reset). There is no upper limit on how far a Lemming can fall before hitting the ground. Lemmings only splatter when hitting the ground; they do not splatter in mid-air.
// Implement a Moore state machine that models this behaviour. areset is positive edge triggered asynchronous reseting the Lemming machine to walk left.


prompt:
module top_module(
	input clk,
	input reset,
	input data,
    output reg shift_ena,
    output reg counting,
    input done_counting,
    output reg done,
    input ack );

test:
`timescale 1 ps/1 ps
`define OK 12
`define INCORRECT 13
module reference_module(
	input clk,
	input reset,
	input data,
    output reg shift_ena,
    output reg counting,
    input done_counting,
    output reg done,
    input ack );

	typedef enum logic[3:0] {
		S, S1, S11, S110, B0, B1, B2, B3, Count, Wait
	} States;

	States state, next;

	always_comb begin
		case (state)
			S: next = States'(data ? S1: S);
			S1: next = States'(data ? S11: S);
			S11: next = States'(data ? S11 : S110);
			S110: next = States'(data ? B0 : S);
			B0: next = B1;
			B1: next = B2;
			B2: next = B3;
			B3: next = Count;
			Count: next = States'(done_counting ? Wait : Count);
			Wait: next = States'(ack ? S : Wait);
			default: next = States'(4'bx);
		endcase
	end

	always @(posedge clk) begin
		if (reset) state <= S;
		else state <= next;
	end

	always_comb begin
		shift_ena = 0; counting = 0; done = 0;
		if (state == B0 || state == B1 || state == B2 || state == B3)
			shift_ena = 1;
		if (state == Count)
			counting = 1;
		if (state == Wait)
			done = 1;

		if (|state === 1'bx) begin
			{shift_ena, counting, done} = 'x;
		end

	end

endmodule

module stimulus_gen (
	input clk,
	output reg reset,
	output reg data, done_counting, ack,
	input tb_match
);
	bit failed = 0;

	always @(posedge clk, negedge clk)
		if (!tb_match)
			failed <= 1;

	initial begin

		@(posedge clk);
		failed <= 0;
		reset <= 1;
		data <= 0;
		done_counting <= 1'bx;
		ack <= 1'bx;
		@(posedge clk)
			data <= 1;
			reset <= 0;
		@(posedge clk) data <= 0;
		@(posedge clk) data <= 0;
		@(posedge clk) data <= 1;
		@(posedge clk) data <= 1;
		@(posedge clk) data <= 0;
		@(posedge clk) data <= 1;
		@(posedge clk);
			data <= 1'bx;
		repeat(4) @(posedge clk);
			done_counting <= 1'b0;
		repeat(4) @(posedge clk);
			done_counting <= 1'b1;
		@(posedge clk);
			done_counting <= 1'bx;
			ack <= 1'b0;
		repeat(3) @(posedge clk);
			ack <= 1'b1;
		@(posedge clk);
			ack <= 1'b0;
			data <= 1'b1;
		@(posedge clk);
			ack <= 1'bx;
			data <= 1'b1;
		@(posedge clk);
			data <= 1'b0;
		@(posedge clk);
			data <= 1'b1;
		@(posedge clk);
			data <= 1'bx;
		repeat(4) @(posedge clk);
			done_counting <= 1'b0;
		repeat(4) @(posedge clk);
			done_counting <= 1'b1;
		@(posedge clk);

		if (failed)
			$display("Hint: Your FSM didn't pass the sample timing diagram posted with the problem statement. Perhaps try debugging that?");

		repeat(5000) @(posedge clk, negedge clk) begin
			reset <= !($random & 255);
			data <= $random;
			done_counting <= !($random & 31);
			ack <= !($random & 31);
		end

		#1 $finish;
	end

endmodule

module tb();

	typedef struct packed {
		int errors;
		int errortime;
		int errors_shift_ena;
		int errortime_shift_ena;
		int errors_counting;
		int errortime_counting;
		int errors_done;
		int errortime_done;

		int clocks;
	} stats;

	stats stats1;

	wire[511:0] wavedrom_title;
	wire wavedrom_enable;
	int wavedrom_hide_after_time;

	reg clk=0;
	initial forever
		#5 clk = ~clk;

	logic reset;
	logic data;
	logic done_counting;
	logic ack;
	logic shift_ena_ref;
	logic shift_ena_dut;
	logic counting_ref;
	logic counting_dut;
	logic done_ref;
	logic done_dut;

	initial begin
		$dumpfile("wave.vcd");
		$dumpvars(1, stim1.clk, tb_mismatch ,clk,reset,data,done_counting,ack,shift_ena_ref,shift_ena_dut,counting_ref,counting_dut,done_ref,done_dut );
	end

	wire tb_match;		// Verification
	wire tb_mismatch = ~tb_match;

	stimulus_gen stim1 (
		.clk,
		.* ,
		.reset,
		.data,
		.done_counting,
		.ack );
	reference_module good1 (
		.clk,
		.reset,
		.data,
		.done_counting,
		.ack,
		.shift_ena(shift_ena_ref),
		.counting(counting_ref),
		.done(done_ref) );

	top_module top_module1 (
		.clk,
		.reset,
		.data,
		.done_counting,
		.ack,
		.shift_ena(shift_ena_dut),
		.counting(counting_dut),
		.done(done_dut) );

	bit strobe = 0;
	task wait_for_end_of_timestep;
		repeat(5) begin
			strobe <= !strobe;  // Try to delay until the very end of the time step.
			@(strobe);
		end
	endtask

	final begin
		if (stats1.errors_shift_ena) $display("Hint: Output '%s' has %0d mismatches. First mismatch occurred at time %0d.", "shift_ena", stats1.errors_shift_ena, stats1.errortime_shift_ena);
		else $display("Hint: Output '%s' has no mismatches.", "shift_ena");
		if (stats1.errors_counting) $display("Hint: Output '%s' has %0d mismatches. First mismatch occurred at time %0d.", "counting", stats1.errors_counting, stats1.errortime_counting);
		else $display("Hint: Output '%s' has no mismatches.", "counting");
		if (stats1.errors_done) $display("Hint: Output '%s' has %0d mismatches. First mismatch occurred at time %0d.", "done", stats1.errors_done, stats1.errortime_done);
		else $display("Hint: Output '%s' has no mismatches.", "done");

		$display("Hint: Total mismatched samples is %1d out of %1d samples\n", stats1.errors, stats1.clocks);
		$display("Simulation finished at %0d ps", $time);
		$display("Mismatches: %1d in %1d samples", stats1.errors, stats1.clocks);
	end

	// Verification: XORs on the right makes any X in good_vector match anything, but X in dut_vector will only match X.
	assign tb_match = ( { shift_ena_ref, counting_ref, done_ref } === ( { shift_ena_ref, counting_ref, done_ref } ^ { shift_ena_dut, counting_dut, done_dut } ^ { shift_ena_ref, counting_ref, done_ref } ) );
	// Use explicit sensitivity list here. @(*) causes NetProc::nex_input() to be called when trying to compute
	// the sensitivity list of the @(strobe) process, which isn't implemented.
	always @(posedge clk, negedge clk) begin

		stats1.clocks++;
		if (!tb_match) begin
			if (stats1.errors == 0) stats1.errortime = $time;
			stats1.errors++;
		end
		if (shift_ena_ref !== ( shift_ena_ref ^ shift_ena_dut ^ shift_ena_ref ))
		begin if (stats1.errors_shift_ena == 0) stats1.errortime_shift_ena = $time;
			stats1.errors_shift_ena = stats1.errors_shift_ena+1'b1; end
		if (counting_ref !== ( counting_ref ^ counting_dut ^ counting_ref ))
		begin if (stats1.errors_counting == 0) stats1.errortime_counting = $time;
			stats1.errors_counting = stats1.errors_counting+1'b1; end
		if (done_ref !== ( done_ref ^ done_dut ^ done_ref ))
		begin if (stats1.errors_done == 0) stats1.errortime_done = $time;
			stats1.errors_done = stats1.errors_done+1'b1; end

	end
endmodule

detail_description:
We want to create a timer that:
// (1) is started when a particular pattern (1101) is detected,
// (2) shifts in 4 more bits to determine the duration to delay,
// (3) waits for the counters to finish counting, and
// (4) notifies the user and waits for the user to acknowledge the timer.
// In this problem, implement just the finite-state machine that controls the timer. The data path (counters and some comparators) are not included here.
// The serial data is available on the data input pin. When the pattern 1101 is received, the state machine must then assert output shift_ena for exactly 4 clock cycles. After that, the state machine asserts its counting output to indicate it is waiting for the counters, and waits until input done_counting is high.At that point, the state machine must assert done to notify the user the timer has timed out, and waits until input ack is 1 before being reset to look for the next occurrence of the start sequence (1101). The state machine should have a active high synchronous reset, setting the state to where it begins searching for the input sequence 1101.


prompt:
module top_module (
	input [7:0] in,
	output reg [2:0] pos
);

test:
`timescale 1 ps/1 ps
`define OK 12
`define INCORRECT 13
module reference_module (
	input [7:0] in,
	output reg [2:0] pos
);

	always @(*) begin
		casez (in)
			default : pos = 2'h0;
			8'bzzzzzzz1: pos = 3'h0;
			8'bzzzzzz1z: pos = 3'h1;
			8'bzzzzz1zz: pos = 3'h2;
			8'bzzzz1zzz: pos = 3'h3;
			8'bzzz1zzzz: pos = 3'h4;
			8'bzz1zzzzz: pos = 3'h5;
			8'bz1zzzzzz: pos = 3'h6;
			8'b1zzzzzzz: pos = 3'h7;
		endcase
	end

endmodule

module stimulus_gen (
	input clk,
	output logic [7:0] in,
	output reg[511:0] wavedrom_title,
	output reg wavedrom_enable
);

// Add two ports to module stimulus_gen:
//    output [511:0] wavedrom_title
//    output reg wavedrom_enable

	task wavedrom_start(input[511:0] title = "");
	endtask

	task wavedrom_stop;
		#1;
	endtask

	initial begin
		@(negedge clk) wavedrom_start("Priority encoder");
			@(posedge clk) in <= 8'h1;
			repeat(8) @(posedge clk) in <= in << 1;
			in <= 8'h10;
			repeat(8) @(posedge clk) in <= in + 1;
		@(negedge clk) wavedrom_stop();

		repeat(50) @(posedge clk, negedge clk) begin
			in <= $urandom;
		end
		repeat(260) @(posedge clk, negedge clk) begin
			in <= in + 1;
		end
		$finish;
	end

endmodule

module tb();

	typedef struct packed {
		int errors;
		int errortime;
		int errors_pos;
		int errortime_pos;

		int clocks;
	} stats;

	stats stats1;

	wire[511:0] wavedrom_title;
	wire wavedrom_enable;
	int wavedrom_hide_after_time;

	reg clk=0;
	initial forever
		#5 clk = ~clk;

	logic [7:0] in;
	logic [2:0] pos_ref;
	logic [2:0] pos_dut;

	initial begin
		$dumpfile("wave.vcd");
		$dumpvars(1, stim1.clk, tb_mismatch ,in,pos_ref,pos_dut );
	end

	wire tb_match;		// Verification
	wire tb_mismatch = ~tb_match;

	stimulus_gen stim1 (
		.clk,
		.* ,
		.in );
	reference_module good1 (
		.in,
		.pos(pos_ref) );

	top_module top_module1 (
		.in,
		.pos(pos_dut) );

	bit strobe = 0;
	task wait_for_end_of_timestep;
		repeat(5) begin
			strobe <= !strobe;  // Try to delay until the very end of the time step.
			@(strobe);
		end
	endtask

	final begin
		if (stats1.errors_pos) $display("Hint: Output '%s' has %0d mismatches. First mismatch occurred at time %0d.", "pos", stats1.errors_pos, stats1.errortime_pos);
		else $display("Hint: Output '%s' has no mismatches.", "pos");

		$display("Hint: Total mismatched samples is %1d out of %1d samples\n", stats1.errors, stats1.clocks);
		$display("Simulation finished at %0d ps", $time);
		$display("Mismatches: %1d in %1d samples", stats1.errors, stats1.clocks);
	end

	// Verification: XORs on the right makes any X in good_vector match anything, but X in dut_vector will only match X.
	assign tb_match = ( { pos_ref } === ( { pos_ref } ^ { pos_dut } ^ { pos_ref } ) );
	// Use explicit sensitivity list here. @(*) causes NetProc::nex_input() to be called when trying to compute
	// the sensitivity list of the @(strobe) process, which isn't implemented.
	always @(posedge clk, negedge clk) begin

		stats1.clocks++;
		if (!tb_match) begin
			if (stats1.errors == 0) stats1.errortime = $time;
			stats1.errors++;
		end
		if (pos_ref !== ( pos_ref ^ pos_dut ^ pos_ref ))
		begin if (stats1.errors_pos == 0) stats1.errortime_pos = $time;
			stats1.errors_pos = stats1.errors_pos+1'b1; end

	end
endmodule

detail_description: Build a priority encoder for 8-bit inputs. Given an 8-bit vector, the output should report the first (least significant) 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.


prompt:
module top_module(
	input a,
	input b,
	output out_assign,
	output reg out_alwaysblock
);

test:
`timescale 1 ps/1 ps
`define OK 12
`define INCORRECT 13
module reference_module(
	input a,
	input b,
	output out_assign,
	output reg out_alwaysblock
);

	assign out_assign = a & b;
	always @(*) out_alwaysblock = a & b;

endmodule

module stimulus_gen (
	input clk,
	output reg a, b,
	output reg[511:0] wavedrom_title,
	output reg wavedrom_enable
);

// Add two ports to module stimulus_gen:
//    output [511:0] wavedrom_title
//    output reg wavedrom_enable

	task wavedrom_start(input[511:0] title = "");
	endtask

	task wavedrom_stop;
		#1;
	endtask

	initial begin
		int count; count = 0;
		{a,b} <= 1'b0;
		wavedrom_start("AND gate");
		repeat(10) @(posedge clk)
			{a,b} <= count++;
		wavedrom_stop();

		repeat(200) @(posedge clk, negedge clk)
			{b,a} <= $random;

		#1 $finish;
	end

endmodule

module tb();

	typedef struct packed {
		int errors;
		int errortime;
		int errors_out_assign;
		int errortime_out_assign;
		int errors_out_alwaysblock;
		int errortime_out_alwaysblock;

		int clocks;
	} stats;

	stats stats1;

	wire[511:0] wavedrom_title;
	wire wavedrom_enable;
	int wavedrom_hide_after_time;

	reg clk=0;
	initial forever
		#5 clk = ~clk;

	logic a;
	logic b;
	logic out_assign_ref;
	logic out_assign_dut;
	logic out_alwaysblock_ref;
	logic out_alwaysblock_dut;

	initial begin
		$dumpfile("wave.vcd");
		$dumpvars(1, stim1.clk, tb_mismatch ,a,b,out_assign_ref,out_assign_dut,out_alwaysblock_ref,out_alwaysblock_dut );
	end

	wire tb_match;		// Verification
	wire tb_mismatch = ~tb_match;

	stimulus_gen stim1 (
		.clk,
		.* ,
		.a,
		.b );
	reference_module good1 (
		.a,
		.b,
		.out_assign(out_assign_ref),
		.out_alwaysblock(out_alwaysblock_ref) );

	top_module top_module1 (
		.a,
		.b,
		.out_assign(out_assign_dut),
		.out_alwaysblock(out_alwaysblock_dut) );

	bit strobe = 0;
	task wait_for_end_of_timestep;
		repeat(5) begin
			strobe <= !strobe;  // Try to delay until the very end of the time step.
			@(strobe);
		end
	endtask

	final begin
		if (stats1.errors_out_assign) $display("Hint: Output '%s' has %0d mismatches. First mismatch occurred at time %0d.", "out_assign", stats1.errors_out_assign, stats1.errortime_out_assign);
		else $display("Hint: Output '%s' has no mismatches.", "out_assign");
		if (stats1.errors_out_alwaysblock) $display("Hint: Output '%s' has %0d mismatches. First mismatch occurred at time %0d.", "out_alwaysblock", stats1.errors_out_alwaysblock, stats1.errortime_out_alwaysblock);
		else $display("Hint: Output '%s' has no mismatches.", "out_alwaysblock");

		$display("Hint: Total mismatched samples is %1d out of %1d samples\n", stats1.errors, stats1.clocks);
		$display("Simulation finished at %0d ps", $time);
		$display("Mismatches: %1d in %1d samples", stats1.errors, stats1.clocks);
	end

	// Verification: XORs on the right makes any X in good_vector match anything, but X in dut_vector will only match X.
	assign tb_match = ( { out_assign_ref, out_alwaysblock_ref } === ( { out_assign_ref, out_alwaysblock_ref } ^ { out_assign_dut, out_alwaysblock_dut } ^ { out_assign_ref, out_alwaysblock_ref } ) );
	// Use explicit sensitivity list here. @(*) causes NetProc::nex_input() to be called when trying to compute
	// the sensitivity list of the @(strobe) process, which isn't implemented.
	always @(posedge clk, negedge clk) begin

		stats1.clocks++;
		if (!tb_match) begin
			if (stats1.errors == 0) stats1.errortime = $time;
			stats1.errors++;
		end
		if (out_assign_ref !== ( out_assign_ref ^ out_assign_dut ^ out_assign_ref ))
		begin if (stats1.errors_out_assign == 0) stats1.errortime_out_assign = $time;
			stats1.errors_out_assign = stats1.errors_out_assign+1'b1; end
		if (out_alwaysblock_ref !== ( out_alwaysblock_ref ^ out_alwaysblock_dut ^ out_alwaysblock_ref ))
		begin if (stats1.errors_out_alwaysblock == 0) stats1.errortime_out_alwaysblock = $time;
			stats1.errors_out_alwaysblock = stats1.errors_out_alwaysblock+1'b1; end

	end
endmodule

detail_description: Build an AND gate using both an assign statement and a combinational always block.


prompt:
module top_module (
	input clk,
	input j,
	input k,
	input areset,
	output out
);

test:
`timescale 1 ps/1 ps
`define OK 12
`define INCORRECT 13
module reference_module (
	input clk,
	input j,
	input k,
	input areset,
	output out
);
	parameter A=0, B=1;
	reg state;
	reg next;

    always_comb begin
		case (state)
			A: next = j ? B : A;
			B: next = k ? A : B;
		endcase
    end

    always @(posedge clk, posedge areset) begin
		if (areset) state <= A;
        else state <= next;
	end

	assign out = (state==B);

endmodule

module stimulus_gen (
	input clk,
	output logic j, k,
	output logic areset,
	output reg[511:0] wavedrom_title,
	output reg wavedrom_enable,
	input tb_match
);

	reg reset;
	assign areset = reset;
	task reset_test(input async=0);
		bit arfail, srfail, datafail;

		@(posedge clk);
		@(posedge clk) reset <= 0;
		repeat(3) @(posedge clk);

		@(negedge clk) begin datafail = !tb_match ; reset <= 1; end
		@(posedge clk) arfail = !tb_match;
		@(posedge clk) begin
			srfail = !tb_match;
			reset <= 0;
		end
		if (srfail)
			$display("Hint: Your reset doesn't seem to be working.");
		else if (arfail && (async || !datafail))
			$display("Hint: Your reset should be %0s, but doesn't appear to be.", async ? "asynchronous" : "synchronous");
		// Don't warn about synchronous reset if the half-cycle before is already wrong. It's more likely
		// a functionality error than the reset being implemented asynchronously.

	endtask

// Add two ports to module stimulus_gen:
//    output [511:0] wavedrom_title
//    output reg wavedrom_enable

	task wavedrom_start(input[511:0] title = "");
	endtask

	task wavedrom_stop;
		#1;
	endtask

	reg [0:11][1:0] d = 24'b000101010010101111111111;

	initial begin
		reset <= 1;
		j <= 0;
		k <= 0;
		@(posedge clk);
		reset <= 0;
		j <= 1;
		@(posedge clk);
		j <= 0;
		wavedrom_start("Reset and transitions");
		reset_test(1);
		for (int i=0;i<12;i++)
			@(posedge clk) {k, j} <= d[i];
		wavedrom_stop();
		repeat(200) @(posedge clk, negedge clk) begin
			{j,k} <= $random;
			reset <= !($random & 7);
		end

		#1 $finish;
	end

endmodule

module tb();

	typedef struct packed {
		int errors;
		int errortime;
		int errors_out;
		int errortime_out;

		int clocks;
	} stats;

	stats stats1;

	wire[511:0] wavedrom_title;
	wire wavedrom_enable;
	int wavedrom_hide_after_time;

	reg clk=0;
	initial forever
		#5 clk = ~clk;

	logic j;
	logic k;
	logic areset;
	logic out_ref;
	logic out_dut;

	initial begin
		$dumpfile("wave.vcd");
		$dumpvars(1, stim1.clk, tb_mismatch ,clk,j,k,areset,out_ref,out_dut );
	end

	wire tb_match;		// Verification
	wire tb_mismatch = ~tb_match;

	stimulus_gen stim1 (
		.clk,
		.* ,
		.j,
		.k,
		.areset );
	reference_module good1 (
		.clk,
		.j,
		.k,
		.areset,
		.out(out_ref) );

	top_module top_module1 (
		.clk,
		.j,
		.k,
		.areset,
		.out(out_dut) );

	bit strobe = 0;
	task wait_for_end_of_timestep;
		repeat(5) begin
			strobe <= !strobe;  // Try to delay until the very end of the time step.
			@(strobe);
		end
	endtask

	final begin
		if (stats1.errors_out) $display("Hint: Output '%s' has %0d mismatches. First mismatch occurred at time %0d.", "out", stats1.errors_out, stats1.errortime_out);
		else $display("Hint: Output '%s' has no mismatches.", "out");

		$display("Hint: Total mismatched samples is %1d out of %1d samples\n", stats1.errors, stats1.clocks);
		$display("Simulation finished at %0d ps", $time);
		$display("Mismatches: %1d in %1d samples", stats1.errors, stats1.clocks);
	end

	// Verification: XORs on the right makes any X in good_vector match anything, but X in dut_vector will only match X.
	assign tb_match = ( { out_ref } === ( { out_ref } ^ { out_dut } ^ { out_ref } ) );
	// Use explicit sensitivity list here. @(*) causes NetProc::nex_input() to be called when trying to compute
	// the sensitivity list of the @(strobe) process, which isn't implemented.
	always @(posedge clk, negedge clk) begin

		stats1.clocks++;
		if (!tb_match) begin
			if (stats1.errors == 0) stats1.errortime = $time;
			stats1.errors++;
		end
		if (out_ref !== ( out_ref ^ out_dut ^ out_ref ))
		begin if (stats1.errors_out == 0) stats1.errortime_out = $time;
			stats1.errors_out = stats1.errors_out+1'b1; end

	end
endmodule

detail_description:
This is a Moore state machine with two states, two inputs, and one output. Implement this state machine in Verilog. Reset is an active-high asynchronous reset to state OFF.

// OFF (out=0) --j=0--> OFF
// OFF (out=0) --j=1--> ON
// ON (out=1) --k=0--> ON
// ON (out=1) --k=1--> OFF


task_id: conwaylife

prompt:
module top_module(
	input clk,
	input load,
	input [255:0] data,
	output reg [255:0] q);

test:
`timescale 1 ps/1 ps
`define OK 12
`define INCORRECT 13
module reference_module(
	input clk,
	input load,
	input [255:0] data,
	output reg [255:0] q);

	logic [323:0] q_pad;
	always@(*) begin
		for (int i=0;i<16;i++)
			q_pad[18*(i+1)+1 +: 16] = q[16*i +: 16];
		q_pad[1 +: 16] = q[16*15 +: 16];
		q_pad[18*17+1 +: 16] = q[0 +: 16];

		for (int i=0; i<18; i++) begin
			q_pad[i*18] = q_pad[i*18+16];
			q_pad[i*18+17] = q_pad[i*18+1];
		end
	end

	always @(posedge clk) begin
		for (int i=0;i<16;i++)
		for (int j=0;j<16;j++) begin
			q[i*16+j] <=
				((q_pad[(i+1)*18+j+1 -1+18] + q_pad[(i+1)*18+j+1 +18] + q_pad[(i+1)*18+j+1 +1+18] +
				q_pad[(i+1)*18+j+1 -1]                                + q_pad[(i+1)*18+j+1+1] +
				q_pad[(i+1)*18+j+1 -1-18]   + q_pad[(i+1)*18+j+1 -18] + q_pad[(i+1)*18+j+1 +1-18]) & 3'h7 | q[i*16+j]) == 3'h3;
		end

		if (load)
			q <= data;

	end

endmodule

module stimulus_gen (
	input clk,
	input tb_match,
	input [255:0] q_ref,
	input [255:0] q_dut,
	output reg load,
	output reg[255:0] data
);

	logic errored = 0;
	int blinker_cycle = 0;

	initial begin
		data <= 3'h7;			// Simple blinker, period 2
		load <= 1;
		@(posedge clk);
		load <= 0;
		data <= 4'hx;
		errored = 0;
		blinker_cycle = 0;
		repeat(5) @(posedge clk) begin
			blinker_cycle++;
			if (!tb_match) begin
				if (!errored) begin
					errored = 1;
					$display("Hint: The first test case is a blinker (initial state = 256'h7). First mismatch occurred at cycle %0d.\nHint:", blinker_cycle);
				end
			end

			if (errored) begin
				$display ("Hint: Cycle %0d:         Your game state       Reference game state", blinker_cycle);
				for (int i=15;i>=0;i--) begin
					$display("Hint:   q[%3d:%3d]     %016b      %016b", i*16+15, i*16, q_dut [ i*16 +: 16 ], q_ref[ i*16 +: 16 ]);
				end
				$display("Hint:\nHint:\n");
			end
		end

		data <= 48'h000200010007;	// Glider, Traveling diagonal down-right.
		load <= 1;
		@(posedge clk);
		@(posedge clk);
		@(posedge clk);
		load <= 0;
		data <= 4'hx;
		errored = 0;
		blinker_cycle = 0;
		repeat(100) @(posedge clk) begin
			blinker_cycle++;
			if (!tb_match) begin
				if (!errored) begin
					errored = 1;
					$display("Hint: The second test case is a glider (initial state = 256'h000200010007). First mismatch occurred at cycle %0d.\nHint:", blinker_cycle);
				end
			end

			if (errored && blinker_cycle < 20) begin
				$display ("Hint: Cycle %0d:         Your game state       Reference game state", blinker_cycle);
				for (int i=15;i>=0;i--) begin
					$display("Hint:   q[%3d:%3d]     %016b      %016b", i*16+15, i*16, q_dut [ i*16 +: 16 ], q_ref[ i*16 +: 16 ]);
				end
				$display("Hint:\nHint:\n");
			end
		end

		data <= 48'h0040001000ce;			// Acorn
		load <= 1;
		@(posedge clk);
		load <= 0;
		repeat(2000) @(posedge clk);

		data <= {$random,$random,$random,$random,$random,$random,$random,$random};		// Some random test cases.
		load <= 1;
		@(posedge clk);
		load <= 0;
		repeat(200) @(posedge clk);

		data <= {$random,$random,$random,$random,$random,$random,$random,$random}&		// Random with more zeros.
				{$random,$random,$random,$random,$random,$random,$random,$random}&
				{$random,$random,$random,$random,$random,$random,$random,$random}&
				{$random,$random,$random,$random,$random,$random,$random,$random};
		load <= 1;
		@(posedge clk);
		load <= 0;
		repeat(200) @(posedge clk);

		#1 $finish;
	end

endmodule

module tb();

	typedef struct packed {
		int errors;
		int errortime;
		int errors_q;
		int errortime_q;

		int clocks;
	} stats;

	stats stats1;

	wire[511:0] wavedrom_title;
	wire wavedrom_enable;
	int wavedrom_hide_after_time;

	reg clk=0;
	initial forever
		#5 clk = ~clk;

	logic load;
	logic [255:0] data;
	logic [255:0] q_ref;
	logic [255:0] q_dut;

	initial begin
		$dumpfile("wave.vcd");
		$dumpvars(1, stim1.clk, tb_mismatch ,clk,load,data,q_ref,q_dut );
	end

	wire tb_match;		// Verification
	wire tb_mismatch = ~tb_match;

	stimulus_gen stim1 (
		.clk,
		.* ,
		.load,
		.data );
	reference_module good1 (
		.clk,
		.load,
		.data,
		.q(q_ref) );

	top_module top_module1 (
		.clk,
		.load,
		.data,
		.q(q_dut) );

	bit strobe = 0;
	task wait_for_end_of_timestep;
		repeat(5) begin
			strobe <= !strobe;  // Try to delay until the very end of the time step.
			@(strobe);
		end
	endtask

	final begin
		if (stats1.errors_q) $display("Hint: Output '%s' has %0d mismatches. First mismatch occurred at time %0d.", "q", stats1.errors_q, stats1.errortime_q);
		else $display("Hint: Output '%s' has no mismatches.", "q");

		$display("Hint: Total mismatched samples is %1d out of %1d samples\n", stats1.errors, stats1.clocks);
		$display("Simulation finished at %0d ps", $time);
		$display("Mismatches: %1d in %1d samples", stats1.errors, stats1.clocks);
	end

	// Verification: XORs on the right makes any X in good_vector match anything, but X in dut_vector will only match X.
	assign tb_match = ( { q_ref } === ( { q_ref } ^ { q_dut } ^ { q_ref } ) );
	// Use explicit sensitivity list here. @(*) causes NetProc::nex_input() to be called when trying to compute
	// the sensitivity list of the @(strobe) process, which isn't implemented.
	always @(posedge clk, negedge clk) begin

		stats1.clocks++;
		if (!tb_match) begin
			if (stats1.errors == 0) stats1.errortime = $time;
			stats1.errors++;
		end
		if (q_ref !== ( q_ref ^ q_dut ^ q_ref ))
		begin if (stats1.errors_q == 0) stats1.errortime_q = $time;
			stats1.errors_q = stats1.errors_q+1'b1; end

	end
endmodule

detail_description:
The "game" is played on a two-dimensional grid of cells, where each cell is either 1 (alive) or 0 (dead). At each time step, each cell changes state depending on how many neighbours it has:
// (1) 0-1 neighbour: Cell becomes 0.
// (2) 2 neighbours: Cell state does not change.
// (3) 3 neighbours: Cell becomes 1.
// (4) 4+ neighbours: Cell becomes 0.
// The game is formulated for an infinite grid. In this circuit, we will use a 16x16 grid. To make things more interesting, we will use a 16x16 toroid, where the sides wrap around to the other side of the grid. For example, the corner cell (0,0) has 8 neighbours: (15,1), (15,0), (15,15), (0,1), (0,15), (1,1), (1,0), and (1,15). The 16x16 grid is represented by a length 256 vector, where each row of 16 cells is represented by a sub-vector: q[15:0] is row 0, q[31:16] is row 1, etc.
// (1) load: Loads data into q at the next clock edge, for loading initial state. Active high synchronous.
// (2) q: The 16x16 current state of the game, updated every clock cycle.
// The game state should advance by one timestep every clock cycle.


prompt:
module top_module (
	input in1,
	input in2,
	input in3,
	output logic out
);

test:
`timescale 1 ps/1 ps
`define OK 12
`define INCORRECT 13
module reference_module (
	input in1,
	input in2,
	input in3,
	output logic out
);

	assign out = (~(in1 ^ in2)) ^ in3;
endmodule

module stimulus_gen (
	input clk,
	output logic in1, in2, in3
);

	initial begin
		repeat(100) @(posedge clk, negedge clk) begin
			{in1, in2, in3} <= $random;
		end

		#1 $finish;
	end

endmodule

module tb();

	typedef struct packed {
		int errors;
		int errortime;
		int errors_out;
		int errortime_out;

		int clocks;
	} stats;

	stats stats1;

	wire[511:0] wavedrom_title;
	wire wavedrom_enable;
	int wavedrom_hide_after_time;

	reg clk=0;
	initial forever
		#5 clk = ~clk;

	logic in1;
	logic in2;
	logic in3;
	logic out_ref;
	logic out_dut;

	initial begin
		$dumpfile("wave.vcd");
		$dumpvars(1, stim1.clk, tb_mismatch ,in1,in2,in3,out_ref,out_dut );
	end

	wire tb_match;		// Verification
	wire tb_mismatch = ~tb_match;

	stimulus_gen stim1 (
		.clk,
		.* ,
		.in1,
		.in2,
		.in3 );
	reference_module good1 (
		.in1,
		.in2,
		.in3,
		.out(out_ref) );

	top_module top_module1 (
		.in1,
		.in2,
		.in3,
		.out(out_dut) );

	bit strobe = 0;
	task wait_for_end_of_timestep;
		repeat(5) begin
			strobe <= !strobe;  // Try to delay until the very end of the time step.
			@(strobe);
		end
	endtask

	final begin
		if (stats1.errors_out) $display("Hint: Output '%s' has %0d mismatches. First mismatch occurred at time %0d.", "out", stats1.errors_out, stats1.errortime_out);
		else $display("Hint: Output '%s' has no mismatches.", "out");

		$display("Hint: Total mismatched samples is %1d out of %1d samples\n", stats1.errors, stats1.clocks);
		$display("Simulation finished at %0d ps", $time);
		$display("Mismatches: %1d in %1d samples", stats1.errors, stats1.clocks);
	end

	// Verification: XORs on the right makes any X in good_vector match anything, but X in dut_vector will only match X.
	assign tb_match = ( { out_ref } === ( { out_ref } ^ { out_dut } ^ { out_ref } ) );
	// Use explicit sensitivity list here. @(*) causes NetProc::nex_input() to be called when trying to compute
	// the sensitivity list of the @(strobe) process, which isn't implemented.
	always @(posedge clk, negedge clk) begin

		stats1.clocks++;
		if (!tb_match) begin
			if (stats1.errors == 0) stats1.errortime = $time;
			stats1.errors++;
		end
		if (out_ref !== ( out_ref ^ out_dut ^ out_ref ))
		begin if (stats1.errors_out == 0) stats1.errortime_out = $time;
			stats1.errors_out = stats1.errors_out+1'b1; end

	end
endmodule

detail_description: Implement in Verilog the following circuit: A two-input XNOR (connected to 'in1' and 'in2) has an output connected to the input of a two-input XOR. The second input of the XOR is 'in3.' The output of the XOR is 'out'.


prompt:
module top_module(
	input x,
	input y,
	output z);

canonical_solution:
	assign z = ~(x^y);

endmodule

test:
`timescale 1 ps/1 ps
`define OK 12
`define INCORRECT 13
module reference_module(
	input x,
	input y,
	output z);

	assign z = ~(x^y);

endmodule

module stimulus_gen (
	input clk,
	output logic x,
	output logic y,
	output reg[511:0] wavedrom_title,
	output reg wavedrom_enable
);

// Add two ports to module stimulus_gen:
//    output [511:0] wavedrom_title
//    output reg wavedrom_enable

	task wavedrom_start(input[511:0] title = "");
	endtask

	task wavedrom_stop;
		#1;
	endtask

	initial begin
		{x,y} <= 0;
		@(negedge clk) wavedrom_start();
			@(posedge clk) {y,x} <= 0;
			@(posedge clk) {y,x} <= 1;
			@(posedge clk) {y,x} <= 2;
			@(posedge clk) {y,x} <= 3;
		@(negedge clk) wavedrom_stop();
		repeat(100) @(posedge clk, negedge clk)
			{x, y} <= $random % 4;
		#1 $finish;
	end

endmodule

module tb();

	typedef struct packed {
		int errors;
		int errortime;
		int errors_z;
		int errortime_z;

		int clocks;
	} stats;

	stats stats1;

	wire[511:0] wavedrom_title;
	wire wavedrom_enable;
	int wavedrom_hide_after_time;

	reg clk=0;
	initial forever
		#5 clk = ~clk;

	logic x;
	logic y;
	logic z_ref;
	logic z_dut;

	initial begin
		$dumpfile("wave.vcd");
		$dumpvars(1, stim1.clk, tb_mismatch ,x,y,z_ref,z_dut );
	end

	wire tb_match;		// Verification
	wire tb_mismatch = ~tb_match;

	stimulus_gen stim1 (
		.clk,
		.* ,
		.x,
		.y );
	reference_module good1 (
		.x,
		.y,
		.z(z_ref) );

	top_module top_module1 (
		.x,
		.y,
		.z(z_dut) );

	bit strobe = 0;
	task wait_for_end_of_timestep;
		repeat(5) begin
			strobe <= !strobe;  // Try to delay until the very end of the time step.
			@(strobe);
		end
	endtask

	final begin
		if (stats1.errors_z) $display("Hint: Output '%s' has %0d mismatches. First mismatch occurred at time %0d.", "z", stats1.errors_z, stats1.errortime_z);
		else $display("Hint: Output '%s' has no mismatches.", "z");

		$display("Hint: Total mismatched samples is %1d out of %1d samples\n", stats1.errors, stats1.clocks);
		$display("Simulation finished at %0d ps", $time);
		$display("Mismatches: %1d in %1d samples", stats1.errors, stats1.clocks);
	end

	// Verification: XORs on the right makes any X in good_vector match anything, but X in dut_vector will only match X.
	assign tb_match = ( { z_ref } === ( { z_ref } ^ { z_dut } ^ { z_ref } ) );
	// Use explicit sensitivity list here. @(*) causes NetProc::nex_input() to be called when trying to compute
	// the sensitivity list of the @(strobe) process, which isn't implemented.
	always @(posedge clk, negedge clk) begin

		stats1.clocks++;
		if (!tb_match) begin
			if (stats1.errors == 0) stats1.errortime = $time;
			stats1.errors++;
		end
		if (z_ref !== ( z_ref ^ z_dut ^ z_ref ))
		begin if (stats1.errors_z == 0) stats1.errortime_z = $time;
			stats1.errors_z = stats1.errors_z+1'b1; end

	end
endmodule


prompt:
module top_module (
	input clk,
	input reset,
	input w,
	output z
);

test:
`timescale 1 ps/1 ps
`define OK 12
`define INCORRECT 13
module reference_module (
	input clk,
	input reset,
	input w,
	output z
);
	parameter A=0, B=1, C=2, D=3, E=4, F=5;
	reg [2:0] state, next;

	always @(posedge clk)
		if (reset)
			state <= A;
		else
			state <= next;

	always_comb begin
		case(state)
			A: next = w ? A : B;
			B: next = w ? D : C;
			C: next = w ? D : E;
			D: next = w ? A : F;
			E: next = w ? D : E;
			F: next = w ? D : C;
			default: next = 'x;
		endcase
	end

	assign z = (state == E || state == F);

endmodule

module stimulus_gen (
	input clk,
	output logic reset,
	output logic w
);

	initial begin
		repeat(200) @(posedge clk, negedge clk) begin
			w <= $random;
			reset <= ($random & 15) == 0;
		end

		#1 $finish;
	end

endmodule

module tb();

	typedef struct packed {
		int errors;
		int errortime;
		int errors_z;
		int errortime_z;

		int clocks;
	} stats;

	stats stats1;

	wire[511:0] wavedrom_title;
	wire wavedrom_enable;
	int wavedrom_hide_after_time;

	reg clk=0;
	initial forever
		#5 clk = ~clk;

	logic reset;
	logic w;
	logic z_ref;
	logic z_dut;

	initial begin
		$dumpfile("wave.vcd");
		$dumpvars(1, stim1.clk, tb_mismatch ,clk,reset,w,z_ref,z_dut );
	end

	wire tb_match;		// Verification
	wire tb_mismatch = ~tb_match;

	stimulus_gen stim1 (
		.clk,
		.* ,
		.reset,
		.w );
	reference_module good1 (
		.clk,
		.reset,
		.w,
		.z(z_ref) );

	top_module top_module1 (
		.clk,
		.reset,
		.w,
		.z(z_dut) );

	bit strobe = 0;
	task wait_for_end_of_timestep;
		repeat(5) begin
			strobe <= !strobe;  // Try to delay until the very end of the time step.
			@(strobe);
		end
	endtask

	final begin
		if (stats1.errors_z) $display("Hint: Output '%s' has %0d mismatches. First mismatch occurred at time %0d.", "z", stats1.errors_z, stats1.errortime_z);
		else $display("Hint: Output '%s' has no mismatches.", "z");

		$display("Hint: Total mismatched samples is %1d out of %1d samples\n", stats1.errors, stats1.clocks);
		$display("Simulation finished at %0d ps", $time);
		$display("Mismatches: %1d in %1d samples", stats1.errors, stats1.clocks);
	end

	// Verification: XORs on the right makes any X in good_vector match anything, but X in dut_vector will only match X.
	assign tb_match = ( { z_ref } === ( { z_ref } ^ { z_dut } ^ { z_ref } ) );
	// Use explicit sensitivity list here. @(*) causes NetProc::nex_input() to be called when trying to compute
	// the sensitivity list of the @(strobe) process, which isn't implemented.
	always @(posedge clk, negedge clk) begin

		stats1.clocks++;
		if (!tb_match) begin
			if (stats1.errors == 0) stats1.errortime = $time;
			stats1.errors++;
		end
		if (z_ref !== ( z_ref ^ z_dut ^ z_ref ))
		begin if (stats1.errors_z == 0) stats1.errortime_z = $time;
			stats1.errors_z = stats1.errors_z+1'b1; end

	end
endmodule


prompt:
module top_module (
	input a,
	input b,
	input c,
	input d,
	output out
);

test:
`timescale 1 ps/1 ps
`define OK 12
`define INCORRECT 13
module reference_module (
	input a,
	input b,
	input c,
	input d,
	output out
);

	assign out = (~c & ~b) | (~d&~a) | (a&c&d) | (b&c&d);

endmodule

module stimulus_gen (
	input clk,
	output reg a, b, c, d,
	output reg[511:0] wavedrom_title,
	output reg wavedrom_enable
);

// Add two ports to module stimulus_gen:
//    output [511:0] wavedrom_title
//    output reg wavedrom_enable

	task wavedrom_start(input[511:0] title = "");
	endtask

	task wavedrom_stop;
		#1;
	endtask

	initial begin
		int count; count = 0;
		{a,b,c,d} <= 4'b0;
		wavedrom_start();
		repeat(16) @(posedge clk)
			{a,b,c,d} <= count++;
		@(negedge clk) wavedrom_stop();

		repeat(200) @(posedge clk, negedge clk)
			{d,c,b,a} <= $urandom;

		#1 $finish;
	end

endmodule

module tb();

	typedef struct packed {
		int errors;
		int errortime;
		int errors_out;
		int errortime_out;

		int clocks;
	} stats;

	stats stats1;

	wire[511:0] wavedrom_title;
	wire wavedrom_enable;
	int wavedrom_hide_after_time;

	reg clk=0;
	initial forever
		#5 clk = ~clk;

	logic a;
	logic b;
	logic c;
	logic d;
	logic out_ref;
	logic out_dut;

	initial begin
		$dumpfile("wave.vcd");
		$dumpvars(1, stim1.clk, tb_mismatch ,a,b,c,d,out_ref,out_dut );
	end

	wire tb_match;		// Verification
	wire tb_mismatch = ~tb_match;

	stimulus_gen stim1 (
		.clk,
		.* ,
		.a,
		.b,
		.c,
		.d );
	reference_module good1 (
		.a,
		.b,
		.c,
		.d,
		.out(out_ref) );

	top_module top_module1 (
		.a,
		.b,
		.c,
		.d,
		.out(out_dut) );

	bit strobe = 0;
	task wait_for_end_of_timestep;
		repeat(5) begin
			strobe <= !strobe;  // Try to delay until the very end of the time step.
			@(strobe);
		end
	endtask

	final begin
		if (stats1.errors_out) $display("Hint: Output '%s' has %0d mismatches. First mismatch occurred at time %0d.", "out", stats1.errors_out, stats1.errortime_out);
		else $display("Hint: Output '%s' has no mismatches.", "out");

		$display("Hint: Total mismatched samples is %1d out of %1d samples\n", stats1.errors, stats1.clocks);
		$display("Simulation finished at %0d ps", $time);
		$display("Mismatches: %1d in %1d samples", stats1.errors, stats1.clocks);
	end

	// Verification: XORs on the right makes any X in good_vector match anything, but X in dut_vector will only match X.
	assign tb_match = ( { out_ref } === ( { out_ref } ^ { out_dut } ^ { out_ref } ) );
	// Use explicit sensitivity list here. @(*) causes NetProc::nex_input() to be called when trying to compute
	// the sensitivity list of the @(strobe) process, which isn't implemented.
	always @(posedge clk, negedge clk) begin

		stats1.clocks++;
		if (!tb_match) begin
			if (stats1.errors == 0) stats1.errortime = $time;
			stats1.errors++;
		end
		if (out_ref !== ( out_ref ^ out_dut ^ out_ref ))
		begin if (stats1.errors_out == 0) stats1.errortime_out = $time;
			stats1.errors_out = stats1.errors_out+1'b1; end

	end
endmodule


prompt:
module top_module (
	input [3:0] in,
	output reg [1:0] pos
);

test:
`timescale 1 ps/1 ps
`define OK 12
`define INCORRECT 13
module reference_module (
	input [3:0] in,
	output reg [1:0] pos
);

	always @(*) begin
		case (in)
			4'h0: pos = 2'h0;
			4'h1: pos = 2'h0;
			4'h2: pos = 2'h1;
			4'h3: pos = 2'h0;
			4'h4: pos = 2'h2;
			4'h5: pos = 2'h0;
			4'h6: pos = 2'h1;
			4'h7: pos = 2'h0;
			4'h8: pos = 2'h3;
			4'h9: pos = 2'h0;
			4'ha: pos = 2'h1;
			4'hb: pos = 2'h0;
			4'hc: pos = 2'h2;
			4'hd: pos = 2'h0;
			4'he: pos = 2'h1;
			4'hf: pos = 2'h0;
			default: pos = 2'b0;
		endcase
	end

endmodule

module stimulus_gen (
	input clk,
	output logic [3:0] in,
	output reg[511:0] wavedrom_title,
	output reg wavedrom_enable
);

// Add two ports to module stimulus_gen:
//    output [511:0] wavedrom_title
//    output reg wavedrom_enable

	task wavedrom_start(input[511:0] title = "");
	endtask

	task wavedrom_stop;
		#1;
	endtask

	initial begin
		@(negedge clk) wavedrom_start("Priority encoder");
			@(posedge clk) in <= 4'h1;
			repeat(4) @(posedge clk) in <= in << 1;
			in <= 0;
			repeat(16) @(posedge clk) in <= in + 1;
		@(negedge clk) wavedrom_stop();

		repeat(50) @(posedge clk, negedge clk) begin
			in <= $urandom;
		end
		$finish;
	end

endmodule

module tb();

	typedef struct packed {
		int errors;
		int errortime;
		int errors_pos;
		int errortime_pos;

		int clocks;
	} stats;

	stats stats1;

	wire[511:0] wavedrom_title;
	wire wavedrom_enable;
	int wavedrom_hide_after_time;

	reg clk=0;
	initial forever
		#5 clk = ~clk;

	logic [3:0] in;
	logic [1:0] pos_ref;
	logic [1:0] pos_dut;

	initial begin
		$dumpfile("wave.vcd");
		$dumpvars(1, stim1.clk, tb_mismatch ,in,pos_ref,pos_dut );
	end

	wire tb_match;		// Verification
	wire tb_mismatch = ~tb_match;

	stimulus_gen stim1 (
		.clk,
		.* ,
		.in );
	reference_module good1 (
		.in,
		.pos(pos_ref) );

	top_module top_module1 (
		.in,
		.pos(pos_dut) );

	bit strobe = 0;
	task wait_for_end_of_timestep;
		repeat(5) begin
			strobe <= !strobe;  // Try to delay until the very end of the time step.
			@(strobe);
		end
	endtask

	final begin
		if (stats1.errors_pos) $display("Hint: Output '%s' has %0d mismatches. First mismatch occurred at time %0d.", "pos", stats1.errors_pos, stats1.errortime_pos);
		else $display("Hint: Output '%s' has no mismatches.", "pos");

		$display("Hint: Total mismatched samples is %1d out of %1d samples\n", stats1.errors, stats1.clocks);
		$display("Simulation finished at %0d ps", $time);
		$display("Mismatches: %1d in %1d samples", stats1.errors, stats1.clocks);
	end

	// Verification: XORs on the right makes any X in good_vector match anything, but X in dut_vector will only match X.
	assign tb_match = ( { pos_ref } === ( { pos_ref } ^ { pos_dut } ^ { pos_ref } ) );
	// Use explicit sensitivity list here. @(*) causes NetProc::nex_input() to be called when trying to compute
	// the sensitivity list of the @(strobe) process, which isn't implemented.
	always @(posedge clk, negedge clk) begin

		stats1.clocks++;
		if (!tb_match) begin
			if (stats1.errors == 0) stats1.errortime = $time;
			stats1.errors++;
		end
		if (pos_ref !== ( pos_ref ^ pos_dut ^ pos_ref ))
		begin if (stats1.errors_pos == 0) stats1.errortime_pos = $time;
			stats1.errors_pos = stats1.errors_pos+1'b1; end

	end
endmodule

detail_description: 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.


prompt:
module top_module (
	input clk,
	input x,
	output z
);

test:
`timescale 1 ps/1 ps
`define OK 12
`define INCORRECT 13
module reference_module (
	input clk,
	input x,
	output z
);

	reg [2:0] s = 0;

	always @(posedge clk) begin
		s <= { s[2] ^ x, ~s[1] & x, ~s[0] | x };
	end

	assign z = ~|s;

endmodule

module stimulus_gen (
	input clk,
	output logic x,
	output reg[511:0] wavedrom_title,
	output reg wavedrom_enable
);

// Add two ports to module stimulus_gen:
//    output [511:0] wavedrom_title
//    output reg wavedrom_enable

	task wavedrom_start(input[511:0] title = "");
	endtask

	task wavedrom_stop;
		#1;
	endtask

	initial begin
		x <= 0;
		@(negedge clk) wavedrom_start();
			@(posedge clk) x <= 2'h0;
			@(posedge clk) x <= 2'h0;
			@(posedge clk) x <= 2'h0;
			@(posedge clk) x <= 2'h0;
			@(posedge clk) x <= 2'h1;
			@(posedge clk) x <= 2'h1;
			@(posedge clk) x <= 2'h1;
			@(posedge clk) x <= 2'h1;
		@(negedge clk) wavedrom_stop();
		repeat(100) @(posedge clk, negedge clk)
			x <= $random;

		$finish;
	end

endmodule

module tb();

	typedef struct packed {
		int errors;
		int errortime;
		int errors_z;
		int errortime_z;

		int clocks;
	} stats;

	stats stats1;

	wire[511:0] wavedrom_title;
	wire wavedrom_enable;
	int wavedrom_hide_after_time;

	reg clk=0;
	initial forever
		#5 clk = ~clk;

	logic x;
	logic z_ref;
	logic z_dut;

	initial begin
		$dumpfile("wave.vcd");
		$dumpvars(1, stim1.clk, tb_mismatch ,clk,x,z_ref,z_dut );
	end

	wire tb_match;		// Verification
	wire tb_mismatch = ~tb_match;

	stimulus_gen stim1 (
		.clk,
		.* ,
		.x );
	reference_module good1 (
		.clk,
		.x,
		.z(z_ref) );

	top_module top_module1 (
		.clk,
		.x,
		.z(z_dut) );

	bit strobe = 0;
	task wait_for_end_of_timestep;
		repeat(5) begin
			strobe <= !strobe;  // Try to delay until the very end of the time step.
			@(strobe);
		end
	endtask

	final begin
		if (stats1.errors_z) $display("Hint: Output '%s' has %0d mismatches. First mismatch occurred at time %0d.", "z", stats1.errors_z, stats1.errortime_z);
		else $display("Hint: Output '%s' has no mismatches.", "z");

		$display("Hint: Total mismatched samples is %1d out of %1d samples\n", stats1.errors, stats1.clocks);
		$display("Simulation finished at %0d ps", $time);
		$display("Mismatches: %1d in %1d samples", stats1.errors, stats1.clocks);
	end

	// Verification: XORs on the right makes any X in good_vector match anything, but X in dut_vector will only match X.
	assign tb_match = ( { z_ref } === ( { z_ref } ^ { z_dut } ^ { z_ref } ) );
	// Use explicit sensitivity list here. @(*) causes NetProc::nex_input() to be called when trying to compute
	// the sensitivity list of the @(strobe) process, which isn't implemented.
	always @(posedge clk, negedge clk) begin

		stats1.clocks++;
		if (!tb_match) begin
			if (stats1.errors == 0) stats1.errortime = $time;
			stats1.errors++;
		end
		if (z_ref !== ( z_ref ^ z_dut ^ z_ref ))
		begin if (stats1.errors_z == 0) stats1.errortime_z = $time;
			stats1.errors_z = stats1.errors_z+1'b1; end

	end
endmodule

detail_description:
Given the finite state machine circuit described below, assume that the D flip-flops are initially reset to zero before the machine begins.

// Build this circuit in Verilog.

// Input x goes to three different two-input gates: a XOR, an AND, and a OR gate. Each of the three gates is connected to the input of a D flip-flop and then the flip-flop outputs all go to a three-input XNOR, whose output is Z. The second input of the XOR is its corresponding flip-flop's output, the second input of the AND is its corresponding flip-flop's complemented output, and finally the second input of the OR is its corresponding flip-flop's complementary output.


prompt:
module top_module(
	input clk,
	input load,
	input [511:0] data,
	output reg [511:0] q);

test:
`timescale 1 ps/1 ps
`define OK 12
`define INCORRECT 13
module reference_module(
	input clk,
	input load,
	input [511:0] data,
	output reg [511:0] q);

	always @(posedge clk) begin
		if (load)
			q <= data;
		else begin
			q <=
			~((q[$bits(q)-1:1] & q[$bits(q)-1:0] & {q[$bits(q)-2:0], 1'b0}) |
			(~q[$bits(q)-1:1] & ~q[$bits(q)-1:0] & ~{q[$bits(q)-2:0], 1'b0}) |
			(q[$bits(q)-1:1] & ~q[$bits(q)-1:0] & ~{q[$bits(q)-2:0], 1'b0}) )
			;
		end
	end
endmodule

module stimulus_gen (
	input clk,
	output reg load,
	output reg[511:0] data,
	output reg[511:0] wavedrom_title,
	output reg wavedrom_enable
);

// Add two ports to module stimulus_gen:
//    output [511:0] wavedrom_title
//    output reg wavedrom_enable

	task wavedrom_start(input[511:0] title = "");
	endtask

	task wavedrom_stop;
		#1;
	endtask

	initial begin
		data <= 0;
		data[0] <= 1'b1;
		load <= 1;
		@(posedge clk); wavedrom_start("Load q[511:0] = 1: See Hint.");
		@(posedge clk);
		@(posedge clk);
		load <= 0;
		repeat(10) @(posedge clk);
		wavedrom_stop();

		data <= 0;
		data[256] <= 1'b1;
		load <= 1;
		@(posedge clk);
		@(posedge clk);
		@(posedge clk);
		load <= 0;
		repeat(1000) @(posedge clk) begin
		end
		data <= 512'h4df;
		load <= 1;
		@(posedge clk);
		load <= 0;
		repeat(1000) @(posedge clk) begin
		end
		data <= $random;
		load <= 1;
		@(posedge clk);
		load <= 0;
		repeat(1000) @(posedge clk) begin
		end

		data <= 0;
		load <= 1;
		repeat (20) @(posedge clk);
		@(posedge clk) data <= 2;
		@(posedge clk) data <= 4;
		@(posedge clk) begin
			data <= 9;
			load <= 0;
		end
		@(posedge clk) data <= 12;
		repeat(100) @(posedge clk);

		#1 $finish;
	end

endmodule

module tb();

	typedef struct packed {
		int errors;
		int errortime;
		int errors_q;
		int errortime_q;

		int clocks;
	} stats;

	stats stats1;

	wire[511:0] wavedrom_title;
	wire wavedrom_enable;
	int wavedrom_hide_after_time;

	reg clk=0;
	initial forever
		#5 clk = ~clk;

	logic load;
	logic [511:0] data;
	logic [511:0] q_ref;
	logic [511:0] q_dut;

	initial begin
		$dumpfile("wave.vcd");
		$dumpvars(1, stim1.clk, tb_mismatch ,clk,load,data,q_ref,q_dut );
	end

	wire tb_match;		// Verification
	wire tb_mismatch = ~tb_match;

	stimulus_gen stim1 (
		.clk,
		.* ,
		.load,
		.data );
	reference_module good1 (
		.clk,
		.load,
		.data,
		.q(q_ref) );

	top_module top_module1 (
		.clk,
		.load,
		.data,
		.q(q_dut) );

	bit strobe = 0;
	task wait_for_end_of_timestep;
		repeat(5) begin
			strobe <= !strobe;  // Try to delay until the very end of the time step.
			@(strobe);
		end
	endtask

	final begin
		if (stats1.errors_q) $display("Hint: Output '%s' has %0d mismatches. First mismatch occurred at time %0d.", "q", stats1.errors_q, stats1.errortime_q);
		else $display("Hint: Output '%s' has no mismatches.", "q");

		$display("Hint: Total mismatched samples is %1d out of %1d samples\n", stats1.errors, stats1.clocks);
		$display("Simulation finished at %0d ps", $time);
		$display("Mismatches: %1d in %1d samples", stats1.errors, stats1.clocks);
	end

	// Verification: XORs on the right makes any X in good_vector match anything, but X in dut_vector will only match X.
	assign tb_match = ( { q_ref } === ( { q_ref } ^ { q_dut } ^ { q_ref } ) );
	// Use explicit sensitivity list here. @(*) causes NetProc::nex_input() to be called when trying to compute
	// the sensitivity list of the @(strobe) process, which isn't implemented.
	always @(posedge clk, negedge clk) begin

		stats1.clocks++;
		if (!tb_match) begin
			if (stats1.errors == 0) stats1.errortime = $time;
			stats1.errors++;
		end
		if (q_ref !== ( q_ref ^ q_dut ^ q_ref ))
		begin if (stats1.errors_q == 0) stats1.errortime_q = $time;
			stats1.errors_q = stats1.errors_q+1'b1; end

	end
endmodule

detail_description:
Rule 110 is a one-dimensional cellular automaton with interesting properties (such as being Turing-complete). There is a one-dimensional array of cells (on or off). At each time step, the state of each cell changes. In Rule 110, the next state of each cell depends only on itself and its two neighbours, according to the following table:
// Left | Center | Right | Center's next state
// 1 | 1 | 1 | 0
// 1 | 1 | 0 | 1
// 1 | 0 | 1 | 1
// 1 | 0 | 0 | 0
// 0 | 1 | 1 | 1
// 0 | 1 | 0 | 1
// 0 | 0 | 1 | 1
// 0 | 0 | 0 | 0
// In this circuit, create a 512-cell system (q[511:0]), and advance by one time step each clock cycle. The synchronous active high load input indicates the state of the system should be loaded with data[511:0]. Assume the boundaries (q[-1] and q[512]) are both zero (off).


prompt:
module top_module (
	input [15:0] in,
	output [7:0] out_hi,
	output [7:0] out_lo
);

canonical_solution:
	assign {out_hi, out_lo} = in;

endmodule

test:
`timescale 1 ps/1 ps
`define OK 12
`define INCORRECT 13
module reference_module (
	input [15:0] in,
	output [7:0] out_hi,
	output [7:0] out_lo
);

	assign {out_hi, out_lo} = in;

endmodule

module stimulus_gen (
	input clk,
	output logic [15:0] in,
	output reg[511:0] wavedrom_title,
	output reg wavedrom_enable
);

// Add two ports to module stimulus_gen:
//    output [511:0] wavedrom_title
//    output reg wavedrom_enable

	task wavedrom_start(input[511:0] title = "");
	endtask

	task wavedrom_stop;
		#1;
	endtask

	always @(posedge clk, negedge clk)
		in <= $random;

	initial begin
		wavedrom_start("Random inputs");
		repeat(10) @(posedge clk);
		wavedrom_stop();
		repeat(100) @(negedge clk);
		$finish;
	end

endmodule

module tb();

	typedef struct packed {
		int errors;
		int errortime;
		int errors_out_hi;
		int errortime_out_hi;
		int errors_out_lo;
		int errortime_out_lo;

		int clocks;
	} stats;

	stats stats1;

	wire[511:0] wavedrom_title;
	wire wavedrom_enable;
	int wavedrom_hide_after_time;

	reg clk=0;
	initial forever
		#5 clk = ~clk;

	logic [15:0] in;
	logic [7:0] out_hi_ref;
	logic [7:0] out_hi_dut;
	logic [7:0] out_lo_ref;
	logic [7:0] out_lo_dut;

	initial begin
		$dumpfile("wave.vcd");
		$dumpvars(1, stim1.clk, tb_mismatch ,in,out_hi_ref,out_hi_dut,out_lo_ref,out_lo_dut );
	end

	wire tb_match;		// Verification
	wire tb_mismatch = ~tb_match;

	stimulus_gen stim1 (
		.clk,
		.* ,
		.in );
	reference_module good1 (
		.in,
		.out_hi(out_hi_ref),
		.out_lo(out_lo_ref) );

	top_module top_module1 (
		.in,
		.out_hi(out_hi_dut),
		.out_lo(out_lo_dut) );

	bit strobe = 0;
	task wait_for_end_of_timestep;
		repeat(5) begin
			strobe <= !strobe;  // Try to delay until the very end of the time step.
			@(strobe);
		end
	endtask

	final begin
		if (stats1.errors_out_hi) $display("Hint: Output '%s' has %0d mismatches. First mismatch occurred at time %0d.", "out_hi", stats1.errors_out_hi, stats1.errortime_out_hi);
		else $display("Hint: Output '%s' has no mismatches.", "out_hi");
		if (stats1.errors_out_lo) $display("Hint: Output '%s' has %0d mismatches. First mismatch occurred at time %0d.", "out_lo", stats1.errors_out_lo, stats1.errortime_out_lo);
		else $display("Hint: Output '%s' has no mismatches.", "out_lo");

		$display("Hint: Total mismatched samples is %1d out of %1d samples\n", stats1.errors, stats1.clocks);
		$display("Simulation finished at %0d ps", $time);
		$display("Mismatches: %1d in %1d samples", stats1.errors, stats1.clocks);
	end

	// Verification: XORs on the right makes any X in good_vector match anything, but X in dut_vector will only match X.
	assign tb_match = ( { out_hi_ref, out_lo_ref } === ( { out_hi_ref, out_lo_ref } ^ { out_hi_dut, out_lo_dut } ^ { out_hi_ref, out_lo_ref } ) );
	// Use explicit sensitivity list here. @(*) causes NetProc::nex_input() to be called when trying to compute
	// the sensitivity list of the @(strobe) process, which isn't implemented.
	always @(posedge clk, negedge clk) begin

		stats1.clocks++;
		if (!tb_match) begin
			if (stats1.errors == 0) stats1.errortime = $time;
			stats1.errors++;
		end
		if (out_hi_ref !== ( out_hi_ref ^ out_hi_dut ^ out_hi_ref ))
		begin if (stats1.errors_out_hi == 0) stats1.errortime_out_hi = $time;
			stats1.errors_out_hi = stats1.errors_out_hi+1'b1; end
		if (out_lo_ref !== ( out_lo_ref ^ out_lo_dut ^ out_lo_ref ))
		begin if (stats1.errors_out_lo == 0) stats1.errortime_out_lo = $time;
			stats1.errors_out_lo = stats1.errors_out_lo+1'b1; end

	end
endmodule

detail_description: Build a combinational circuit that splits an input half-word (16 bits, [15:0] ) into lower [7:0] and upper [15:8] bytes.


prompt:
module top_module(
	input [2:0] vec,
	output [2:0] outv,
	output o2,
	output o1,
	output o0
);

test:
`timescale 1 ps/1 ps
`define OK 12
`define INCORRECT 13
module reference_module(
	input [2:0] vec,
	output [2:0] outv,
	output o2,
	output o1,
	output o0
);

	assign outv = vec;
	assign {o2, o1, o0} = vec;

endmodule

module stimulus_gen (
	input clk,
	output reg [2:0] vec,
	output reg[511:0] wavedrom_title,
	output reg wavedrom_enable
);

// Add two ports to module stimulus_gen:
//    output [511:0] wavedrom_title
//    output reg wavedrom_enable

	task wavedrom_start(input[511:0] title = "");
	endtask

	task wavedrom_stop;
		#1;
	endtask

	initial begin
		int count; count = 0;
		vec <= 3'b0;
		@(negedge clk);
		wavedrom_start();
		repeat(10) @(posedge clk)
			vec <= count++;
		wavedrom_stop();

		#1 $finish;
	end

endmodule

module tb();

	typedef struct packed {
		int errors;
		int errortime;
		int errors_outv;
		int errortime_outv;
		int errors_o2;
		int errortime_o2;
		int errors_o1;
		int errortime_o1;
		int errors_o0;
		int errortime_o0;

		int clocks;
	} stats;

	stats stats1;

	wire[511:0] wavedrom_title;
	wire wavedrom_enable;
	int wavedrom_hide_after_time;

	reg clk=0;
	initial forever
		#5 clk = ~clk;

	logic [2:0] vec;
	logic [2:0] outv_ref;
	logic [2:0] outv_dut;
	logic o2_ref;
	logic o2_dut;
	logic o1_ref;
	logic o1_dut;
	logic o0_ref;
	logic o0_dut;

	initial begin
		$dumpfile("wave.vcd");
		$dumpvars(1, stim1.clk, tb_mismatch ,vec,outv_ref,outv_dut,o2_ref,o2_dut,o1_ref,o1_dut,o0_ref,o0_dut );
	end

	wire tb_match;		// Verification
	wire tb_mismatch = ~tb_match;

	stimulus_gen stim1 (
		.clk,
		.* ,
		.vec );
	reference_module good1 (
		.vec,
		.outv(outv_ref),
		.o2(o2_ref),
		.o1(o1_ref),
		.o0(o0_ref) );

	top_module top_module1 (
		.vec,
		.outv(outv_dut),
		.o2(o2_dut),
		.o1(o1_dut),
		.o0(o0_dut) );

	bit strobe = 0;
	task wait_for_end_of_timestep;
		repeat(5) begin
			strobe <= !strobe;  // Try to delay until the very end of the time step.
			@(strobe);
		end
	endtask

	final begin
		if (stats1.errors_outv) $display("Hint: Output '%s' has %0d mismatches. First mismatch occurred at time %0d.", "outv", stats1.errors_outv, stats1.errortime_outv);
		else $display("Hint: Output '%s' has no mismatches.", "outv");
		if (stats1.errors_o2) $display("Hint: Output '%s' has %0d mismatches. First mismatch occurred at time %0d.", "o2", stats1.errors_o2, stats1.errortime_o2);
		else $display("Hint: Output '%s' has no mismatches.", "o2");
		if (stats1.errors_o1) $display("Hint: Output '%s' has %0d mismatches. First mismatch occurred at time %0d.", "o1", stats1.errors_o1, stats1.errortime_o1);
		else $display("Hint: Output '%s' has no mismatches.", "o1");
		if (stats1.errors_o0) $display("Hint: Output '%s' has %0d mismatches. First mismatch occurred at time %0d.", "o0", stats1.errors_o0, stats1.errortime_o0);
		else $display("Hint: Output '%s' has no mismatches.", "o0");

		$display("Hint: Total mismatched samples is %1d out of %1d samples\n", stats1.errors, stats1.clocks);
		$display("Simulation finished at %0d ps", $time);
		$display("Mismatches: %1d in %1d samples", stats1.errors, stats1.clocks);
	end

	// Verification: XORs on the right makes any X in good_vector match anything, but X in dut_vector will only match X.
	assign tb_match = ( { outv_ref, o2_ref, o1_ref, o0_ref } === ( { outv_ref, o2_ref, o1_ref, o0_ref } ^ { outv_dut, o2_dut, o1_dut, o0_dut } ^ { outv_ref, o2_ref, o1_ref, o0_ref } ) );
	// Use explicit sensitivity list here. @(*) causes NetProc::nex_input() to be called when trying to compute
	// the sensitivity list of the @(strobe) process, which isn't implemented.
	always @(posedge clk, negedge clk) begin

		stats1.clocks++;
		if (!tb_match) begin
			if (stats1.errors == 0) stats1.errortime = $time;
			stats1.errors++;
		end
		if (outv_ref !== ( outv_ref ^ outv_dut ^ outv_ref ))
		begin if (stats1.errors_outv == 0) stats1.errortime_outv = $time;
			stats1.errors_outv = stats1.errors_outv+1'b1; end
		if (o2_ref !== ( o2_ref ^ o2_dut ^ o2_ref ))
		begin if (stats1.errors_o2 == 0) stats1.errortime_o2 = $time;
			stats1.errors_o2 = stats1.errors_o2+1'b1; end
		if (o1_ref !== ( o1_ref ^ o1_dut ^ o1_ref ))
		begin if (stats1.errors_o1 == 0) stats1.errortime_o1 = $time;
			stats1.errors_o1 = stats1.errors_o1+1'b1; end
		if (o0_ref !== ( o0_ref ^ o0_dut ^ o0_ref ))
		begin if (stats1.errors_o0 == 0) stats1.errortime_o0 = $time;
			stats1.errors_o0 = stats1.errors_o0+1'b1; end

	end
endmodule

detail_description: Build a circuit that has one 3-bit input, then outputs the same vector, and also splits it into three separate 1-bit outputs. Connect output o0 to the input vector's position 0, o1 to position 1, etc.


prompt:
module top_module(
	input clk,
	input shift_ena,
	input count_ena,
	input data,
	output reg [3:0] q);

test:
`timescale 1 ps/1 ps
`define OK 12
`define INCORRECT 13
module reference_module(
	input clk,
	input shift_ena,
	input count_ena,
	input data,
	output reg [3:0] q);

	always @(posedge clk) begin
		if (shift_ena)
			q <= { q[2:0], data };
		else if (count_ena)
			q <= q - 1'b1;
	end

endmodule

module stimulus_gen (
	input clk,
	output reg shift_ena, count_ena, data,
	output reg[511:0] wavedrom_title,
	output reg wavedrom_enable
);

// Add two ports to module stimulus_gen:
//    output [511:0] wavedrom_title
//    output reg wavedrom_enable

	task wavedrom_start(input[511:0] title = "");
	endtask

	task wavedrom_stop;
		#1;
	endtask

	initial begin
		data <= 0;
		shift_ena <= 1;
		count_ena <= 0;
		repeat(5) @(posedge clk);

		data <= 1;
		shift_ena <= 0;
		count_ena <= 0;
		@(posedge clk);
		wavedrom_start("Shift mode");
		@(posedge clk) shift_ena <= 1;
		repeat(2) @(posedge clk) shift_ena <= 0;
		@(posedge clk) shift_ena <= 1;
		repeat(4) @(posedge clk);
		@(posedge clk) data <= 0;
		repeat(4) @(posedge clk);
		wavedrom_stop();

		data <= 1;
		shift_ena <= 1;
		repeat(4) @(posedge clk);
		shift_ena <= 0;
		wavedrom_start("Count mode");
		@(posedge clk) count_ena <= 1;
		repeat(2) @(posedge clk) count_ena <= 0;
		@(posedge clk) count_ena <= 1;
		repeat(4) @(posedge clk);
		@(posedge clk) data <= 0;
		repeat(4) @(posedge clk);
		wavedrom_stop();

		repeat(2000) @(posedge clk, negedge clk) begin
			{shift_ena, count_ena} <= $unsigned($random) % 3;
			data <= $random;
		end
		#1 $finish;
	end

endmodule

module tb();

	typedef struct packed {
		int errors;
		int errortime;
		int errors_q;
		int errortime_q;

		int clocks;
	} stats;

	stats stats1;

	wire[511:0] wavedrom_title;
	wire wavedrom_enable;
	int wavedrom_hide_after_time;

	reg clk=0;
	initial forever
		#5 clk = ~clk;

	logic shift_ena;
	logic count_ena;
	logic data;
	logic [3:0] q_ref;
	logic [3:0] q_dut;

	initial begin
		$dumpfile("wave.vcd");
		$dumpvars(1, stim1.clk, tb_mismatch ,clk,shift_ena,count_ena,data,q_ref,q_dut );
	end

	wire tb_match;		// Verification
	wire tb_mismatch = ~tb_match;

	stimulus_gen stim1 (
		.clk,
		.* ,
		.shift_ena,
		.count_ena,
		.data );
	reference_module good1 (
		.clk,
		.shift_ena,
		.count_ena,
		.data,
		.q(q_ref) );

	top_module top_module1 (
		.clk,
		.shift_ena,
		.count_ena,
		.data,
		.q(q_dut) );

	bit strobe = 0;
	task wait_for_end_of_timestep;
		repeat(5) begin
			strobe <= !strobe;  // Try to delay until the very end of the time step.
			@(strobe);
		end
	endtask

	final begin
		if (stats1.errors_q) $display("Hint: Output '%s' has %0d mismatches. First mismatch occurred at time %0d.", "q", stats1.errors_q, stats1.errortime_q);
		else $display("Hint: Output '%s' has no mismatches.", "q");

		$display("Hint: Total mismatched samples is %1d out of %1d samples\n", stats1.errors, stats1.clocks);
		$display("Simulation finished at %0d ps", $time);
		$display("Mismatches: %1d in %1d samples", stats1.errors, stats1.clocks);
	end

	// Verification: XORs on the right makes any X in good_vector match anything, but X in dut_vector will only match X.
	assign tb_match = ( { q_ref } === ( { q_ref } ^ { q_dut } ^ { q_ref } ) );
	// Use explicit sensitivity list here. @(*) causes NetProc::nex_input() to be called when trying to compute
	// the sensitivity list of the @(strobe) process, which isn't implemented.
	always @(posedge clk, negedge clk) begin

		stats1.clocks++;
		if (!tb_match) begin
			if (stats1.errors == 0) stats1.errortime = $time;
			stats1.errors++;
		end
		if (q_ref !== ( q_ref ^ q_dut ^ q_ref ))
		begin if (stats1.errors_q == 0) stats1.errortime_q = $time;
			stats1.errors_q = stats1.errors_q+1'b1; end

	end
endmodule

detail_description: Build a four-bit shift register that also acts as a down counter. Data is shifted in most-significant-bit first when shift_ena is 1. The number currently in the shift register is decremented when count_ena is 1. Since the full system doesn't ever use shift_ena and count_ena together, it does not matter what your circuit does if both control inputs are 1 (This mainly means that it doesn't matter which case gets higher priority).


prompt:
module top_module(
	input clk,
	input [7:0] d,
	output reg [7:0] q);

test:
`timescale 1 ps/1 ps
`define OK 12
`define INCORRECT 13
module reference_module(
	input clk,
	input [7:0] d,
	output reg [7:0] q);

	initial
		q = 8'h0;

	always @(posedge clk)
		q <= d;

endmodule

module stimulus_gen (
	input clk,
	output reg [7:0] d,
	output reg[511:0] wavedrom_title,
	output reg wavedrom_enable
);

// Add two ports to module stimulus_gen:
//    output [511:0] wavedrom_title
//    output reg wavedrom_enable

	task wavedrom_start(input[511:0] title = "");
	endtask

	task wavedrom_stop;
		#1;
	endtask

	always @(posedge clk, negedge clk)
		d <= $random % 256;

	initial begin
		@(posedge clk);
		wavedrom_start("Positive-edge triggered DFF");
		repeat(10) @(posedge clk);
		wavedrom_stop();
		#100;
		$finish;
	end

endmodule

module tb();

	typedef struct packed {
		int errors;
		int errortime;
		int errors_q;
		int errortime_q;

		int clocks;
	} stats;

	stats stats1;

	wire[511:0] wavedrom_title;
	wire wavedrom_enable;
	int wavedrom_hide_after_time;

	reg clk=0;
	initial forever
		#5 clk = ~clk;

	logic [7:0] d;
	logic [7:0] q_ref;
	logic [7:0] q_dut;

	initial begin
		$dumpfile("wave.vcd");
		$dumpvars(1, stim1.clk, tb_mismatch ,clk,d,q_ref,q_dut );
	end

	wire tb_match;		// Verification
	wire tb_mismatch = ~tb_match;

	stimulus_gen stim1 (
		.clk,
		.* ,
		.d );
	reference_module good1 (
		.clk,
		.d,
		.q(q_ref) );

	top_module top_module1 (
		.clk,
		.d,
		.q(q_dut) );

	bit strobe = 0;
	task wait_for_end_of_timestep;
		repeat(5) begin
			strobe <= !strobe;  // Try to delay until the very end of the time step.
			@(strobe);
		end
	endtask

	final begin
		if (stats1.errors_q) $display("Hint: Output '%s' has %0d mismatches. First mismatch occurred at time %0d.", "q", stats1.errors_q, stats1.errortime_q);
		else $display("Hint: Output '%s' has no mismatches.", "q");

		$display("Hint: Total mismatched samples is %1d out of %1d samples\n", stats1.errors, stats1.clocks);
		$display("Simulation finished at %0d ps", $time);
		$display("Mismatches: %1d in %1d samples", stats1.errors, stats1.clocks);
	end

	// Verification: XORs on the right makes any X in good_vector match anything, but X in dut_vector will only match X.
	assign tb_match = ( { q_ref } === ( { q_ref } ^ { q_dut } ^ { q_ref } ) );
	// Use explicit sensitivity list here. @(*) causes NetProc::nex_input() to be called when trying to compute
	// the sensitivity list of the @(strobe) process, which isn't implemented.
	always @(posedge clk, negedge clk) begin

		stats1.clocks++;
		if (!tb_match) begin
			if (stats1.errors == 0) stats1.errortime = $time;
			stats1.errors++;
		end
		if (q_ref !== ( q_ref ^ q_dut ^ q_ref ))
		begin if (stats1.errors_q == 0) stats1.errortime_q = $time;
			stats1.errors_q = stats1.errors_q+1'b1; end

	end
endmodule

detail_description: Create 8 D flip-flops. All DFFs should be triggered by the positive edge of clk.


task_id: xnorgate

prompt:
module top_module(
	input a,
	input b,
	output out
);

canonical_solution:
	assign out = ~(a^b);

endmodule

test:
`timescale 1 ps/1 ps
`define OK 12
`define INCORRECT 13
module reference_module(
	input a,
	input b,
	output out
);

	assign out = ~(a^b);

endmodule

module stimulus_gen (
	input clk,
	output reg a, b,
	output reg[511:0] wavedrom_title,
	output reg wavedrom_enable
);

// Add two ports to module stimulus_gen:
//    output [511:0] wavedrom_title
//    output reg wavedrom_enable

	task wavedrom_start(input[511:0] title = "");
	endtask

	task wavedrom_stop;
		#1;
	endtask

	initial begin
		int count; count = 0;
		{a,b} <= 1'b0;
		wavedrom_start("XNOR gate");
		repeat(10) @(posedge clk)
			{a,b} <= count++;
		wavedrom_stop();

		repeat(200) @(posedge clk, negedge clk)
			{b,a} <= $random;

		#1 $finish;
	end

endmodule

module tb();

	typedef struct packed {
		int errors;
		int errortime;
		int errors_out;
		int errortime_out;

		int clocks;
	} stats;

	stats stats1;

	wire[511:0] wavedrom_title;
	wire wavedrom_enable;
	int wavedrom_hide_after_time;

	reg clk=0;
	initial forever
		#5 clk = ~clk;

	logic a;
	logic b;
	logic out_ref;
	logic out_dut;

	initial begin
		$dumpfile("wave.vcd");
		$dumpvars(1, stim1.clk, tb_mismatch ,a,b,out_ref,out_dut );
	end

	wire tb_match;		// Verification
	wire tb_mismatch = ~tb_match;

	stimulus_gen stim1 (
		.clk,
		.* ,
		.a,
		.b );
	reference_module good1 (
		.a,
		.b,
		.out(out_ref) );

	top_module top_module1 (
		.a,
		.b,
		.out(out_dut) );

	bit strobe = 0;
	task wait_for_end_of_timestep;
		repeat(5) begin
			strobe <= !strobe;  // Try to delay until the very end of the time step.
			@(strobe);
		end
	endtask

	final begin
		if (stats1.errors_out) $display("Hint: Output '%s' has %0d mismatches. First mismatch occurred at time %0d.", "out", stats1.errors_out, stats1.errortime_out);
		else $display("Hint: Output '%s' has no mismatches.", "out");

		$display("Hint: Total mismatched samples is %1d out of %1d samples\n", stats1.errors, stats1.clocks);
		$display("Simulation finished at %0d ps", $time);
		$display("Mismatches: %1d in %1d samples", stats1.errors, stats1.clocks);
	end

	// Verification: XORs on the right makes any X in good_vector match anything, but X in dut_vector will only match X.
	assign tb_match = ( { out_ref } === ( { out_ref } ^ { out_dut } ^ { out_ref } ) );
	// Use explicit sensitivity list here. @(*) causes NetProc::nex_input() to be called when trying to compute
	// the sensitivity list of the @(strobe) process, which isn't implemented.
	always @(posedge clk, negedge clk) begin

		stats1.clocks++;
		if (!tb_match) begin
			if (stats1.errors == 0) stats1.errortime = $time;
			stats1.errors++;
		end
		if (out_ref !== ( out_ref ^ out_dut ^ out_ref ))
		begin if (stats1.errors_out == 0) stats1.errortime_out = $time;
			stats1.errors_out = stats1.errors_out+1'b1; end

	end
endmodule

detail_description: Create a module that implements an XNOR gate.


prompt:
module top_module (
	input clk,
	input areset,
	input bump_left,
	input bump_right,
	input ground,
	input dig,
	output walk_left,
	output walk_right,
	output aaah,
	output digging
);

test:
`timescale 1 ps/1 ps
`define OK 12
`define INCORRECT 13
module reference_module (
	input clk,
	input areset,
	input bump_left,
	input bump_right,
	input ground,
	input dig,
	output walk_left,
	output walk_right,
	output aaah,
	output digging
);
	parameter WL=0, WR=1, FALLL=2, FALLR=3, DIGL=4, DIGR=5;
	reg [2:0] state;
	reg [2:0] next;

    always_comb begin
		case (state)
			WL: if (!ground) next = FALLL;
				else if (dig) next = DIGL;
				else if (bump_left) next = WR;
				else next = WL;
			WR:
				if (!ground) next = FALLR;
				else if (dig) next = DIGR;
				else if (bump_right) next = WL;
				else next = WR;
			FALLL: next = ground ? WL : FALLL;
			FALLR: next = ground ? WR : FALLR;
			DIGL: next = ground ? DIGL : FALLL;
			DIGR: next = ground ? DIGR : FALLR;
		endcase
    end

    always @(posedge clk, posedge areset) begin
		if (areset) state <= WL;
        else state <= next;
	end

	assign walk_left = (state==WL);
	assign walk_right = (state==WR);
	assign aaah = (state == FALLL) || (state == FALLR);
	assign digging = (state == DIGL) || (state == DIGR);

endmodule

module stimulus_gen (
	input clk,
	output logic areset,
	output logic bump_left,
	output logic bump_right,
	output logic dig,
	output logic ground,
	output reg[511:0] wavedrom_title,
	output reg wavedrom_enable,
	input tb_match
);
	reg reset;
	assign areset = reset;

	task reset_test(input async=0);
		bit arfail, srfail, datafail;

		@(posedge clk);
		@(posedge clk) reset <= 0;
		repeat(3) @(posedge clk);

		@(negedge clk) begin datafail = !tb_match ; reset <= 1; end
		@(posedge clk) arfail = !tb_match;
		@(posedge clk) begin
			srfail = !tb_match;
			reset <= 0;
		end
		if (srfail)
			$display("Hint: Your reset doesn't seem to be working.");
		else if (arfail && (async || !datafail))
			$display("Hint: Your reset should be %0s, but doesn't appear to be.", async ? "asynchronous" : "synchronous");
		// Don't warn about synchronous reset if the half-cycle before is already wrong. It's more likely
		// a functionality error than the reset being implemented asynchronously.

	endtask

// Add two ports to module stimulus_gen:
//    output [511:0] wavedrom_title
//    output reg wavedrom_enable

	task wavedrom_start(input[511:0] title = "");
	endtask

	task wavedrom_stop;
		#1;
	endtask

	wire [0:13][3:0] d = {
		4'h2,
		4'h2,
		4'h3,
		4'h2,
		4'ha,
		4'h2,
		4'h0,
		4'h0,
		4'h0,
		4'h3,
		4'h2,
		4'h2,
		4'h2,
		4'h2
	};

	initial begin
		reset <= 1'b1;
		{bump_left, bump_right, ground, dig} <= 4'h2;
		reset_test(1);

		reset <= 1'b1;
		@(posedge clk);
		reset <= 0;

		@(negedge clk);
		wavedrom_start("Digging");
		for (int i=0;i<14;i++)
			@(posedge clk) {bump_left, bump_right, ground, dig} <= d[i];
		wavedrom_stop();

		repeat(400) @(posedge clk, negedge clk) begin
			{dig, bump_right, bump_left} <= $random & $random;
			ground <= |($random & 7);
			reset <= !($random & 31);
		end

		#1 $finish;
	end

endmodule

module tb();

	typedef struct packed {
		int errors;
		int errortime;
		int errors_walk_left;
		int errortime_walk_left;
		int errors_walk_right;
		int errortime_walk_right;
		int errors_aaah;
		int errortime_aaah;
		int errors_digging;
		int errortime_digging;

		int clocks;
	} stats;

	stats stats1;

	wire[511:0] wavedrom_title;
	wire wavedrom_enable;
	int wavedrom_hide_after_time;

	reg clk=0;
	initial forever
		#5 clk = ~clk;

	logic areset;
	logic bump_left;
	logic bump_right;
	logic ground;
	logic dig;
	logic walk_left_ref;
	logic walk_left_dut;
	logic walk_right_ref;
	logic walk_right_dut;
	logic aaah_ref;
	logic aaah_dut;
	logic digging_ref;
	logic digging_dut;

	initial begin
		$dumpfile("wave.vcd");
		$dumpvars(1, stim1.clk, tb_mismatch ,clk,areset,bump_left,bump_right,ground,dig,walk_left_ref,walk_left_dut,walk_right_ref,walk_right_dut,aaah_ref,aaah_dut,digging_ref,digging_dut );
	end

	wire tb_match;		// Verification
	wire tb_mismatch = ~tb_match;

	stimulus_gen stim1 (
		.clk,
		.* ,
		.areset,
		.bump_left,
		.bump_right,
		.ground,
		.dig );
	reference_module good1 (
		.clk,
		.areset,
		.bump_left,
		.bump_right,
		.ground,
		.dig,
		.walk_left(walk_left_ref),
		.walk_right(walk_right_ref),
		.aaah(aaah_ref),
		.digging(digging_ref) );

	top_module top_module1 (
		.clk,
		.areset,
		.bump_left,
		.bump_right,
		.ground,
		.dig,
		.walk_left(walk_left_dut),
		.walk_right(walk_right_dut),
		.aaah(aaah_dut),
		.digging(digging_dut) );

	bit strobe = 0;
	task wait_for_end_of_timestep;
		repeat(5) begin
			strobe <= !strobe;  // Try to delay until the very end of the time step.
			@(strobe);
		end
	endtask

	final begin
		if (stats1.errors_walk_left) $display("Hint: Output '%s' has %0d mismatches. First mismatch occurred at time %0d.", "walk_left", stats1.errors_walk_left, stats1.errortime_walk_left);
		else $display("Hint: Output '%s' has no mismatches.", "walk_left");
		if (stats1.errors_walk_right) $display("Hint: Output '%s' has %0d mismatches. First mismatch occurred at time %0d.", "walk_right", stats1.errors_walk_right, stats1.errortime_walk_right);
		else $display("Hint: Output '%s' has no mismatches.", "walk_right");
		if (stats1.errors_aaah) $display("Hint: Output '%s' has %0d mismatches. First mismatch occurred at time %0d.", "aaah", stats1.errors_aaah, stats1.errortime_aaah);
		else $display("Hint: Output '%s' has no mismatches.", "aaah");
		if (stats1.errors_digging) $display("Hint: Output '%s' has %0d mismatches. First mismatch occurred at time %0d.", "digging", stats1.errors_digging, stats1.errortime_digging);
		else $display("Hint: Output '%s' has no mismatches.", "digging");

		$display("Hint: Total mismatched samples is %1d out of %1d samples\n", stats1.errors, stats1.clocks);
		$display("Simulation finished at %0d ps", $time);
		$display("Mismatches: %1d in %1d samples", stats1.errors, stats1.clocks);
	end

	// Verification: XORs on the right makes any X in good_vector match anything, but X in dut_vector will only match X.
	assign tb_match = ( { walk_left_ref, walk_right_ref, aaah_ref, digging_ref } === ( { walk_left_ref, walk_right_ref, aaah_ref, digging_ref } ^ { walk_left_dut, walk_right_dut, aaah_dut, digging_dut } ^ { walk_left_ref, walk_right_ref, aaah_ref, digging_ref } ) );
	// Use explicit sensitivity list here. @(*) causes NetProc::nex_input() to be called when trying to compute
	// the sensitivity list of the @(strobe) process, which isn't implemented.
	always @(posedge clk, negedge clk) begin

		stats1.clocks++;
		if (!tb_match) begin
			if (stats1.errors == 0) stats1.errortime = $time;
			stats1.errors++;
		end
		if (walk_left_ref !== ( walk_left_ref ^ walk_left_dut ^ walk_left_ref ))
		begin if (stats1.errors_walk_left == 0) stats1.errortime_walk_left = $time;
			stats1.errors_walk_left = stats1.errors_walk_left+1'b1; end
		if (walk_right_ref !== ( walk_right_ref ^ walk_right_dut ^ walk_right_ref ))
		begin if (stats1.errors_walk_right == 0) stats1.errortime_walk_right = $time;
			stats1.errors_walk_right = stats1.errors_walk_right+1'b1; end
		if (aaah_ref !== ( aaah_ref ^ aaah_dut ^ aaah_ref ))
		begin if (stats1.errors_aaah == 0) stats1.errortime_aaah = $time;
			stats1.errors_aaah = stats1.errors_aaah+1'b1; end
		if (digging_ref !== ( digging_ref ^ digging_dut ^ digging_ref ))
		begin if (stats1.errors_digging == 0) stats1.errortime_digging = $time;
			stats1.errors_digging = stats1.errors_digging+1'b1; end

	end
endmodule

detail_description:
The game Lemmings involves critters with fairly simple brains. So simple that we are going to model it using a finite state machine. In the Lemmings' 2D world, Lemmings can be in one of two states: walking left (walk_left is 1) or walking right (walk_right is 1). It will switch directions if it hits an obstacle. In particular, if a Lemming is bumped on the left (by receiving a 1 on bump_left), it will walk right. If it's bumped on the right (by receiving a 1 on bump_right), it will walk left. If it's bumped on both sides at the same time, it will still switch directions.
// In addition to walking left and right and changing direction when bumped, when ground=0, the Lemming will fall and say "aaah!". When the ground reappears (ground=1), the Lemming will resume walking in the same direction as before the fall. Being bumped while falling does not affect the walking direction, and being bumped in the same cycle as ground disappears (but not yet falling), or when the ground reappears while still falling, also does not affect the walking direction.
// In addition to walking and falling, Lemmings can sometimes be told to do useful things, like dig (it starts digging when dig=1). A Lemming can dig if it is currently walking on ground (ground=1 and not falling), and will continue digging until it reaches the other side (ground=0). At that point, since there is no ground, it will fall (aaah!), then continue walking in its original direction once it hits ground again. As with falling, being bumped while digging has no effect, and being told to dig when falling or when there is no ground is ignored. (In other words, a walking Lemming can fall, dig, or switch directions. If more than one of these conditions are satisfied, fall has higher precedence than dig, which has higher precedence than switching directions.)
// Implement a Moore state machine that models this behaviour. areset is positive edge triggered asynchronous reseting the Lemming machine to walk left.