prompt:
module top_module(
	input [1:0] A,
	input [1:0] B,
	output z);

canonical_solution:
	assign z = A[1:0]==B[1:0];

endmodule

test:
`timescale 1 ps/1 ps
`define OK 12
`define INCORRECT 13
/*
	Midterm 2015 Question 1k. 2-bit equality comparator.
*/
module reference_module(
	input [1:0] A,
	input [1:0] B,
	output z);

	assign z = A[1:0]==B[1:0];

endmodule

module stimulus_gen (
	input clk,
	output logic [1:0] A,
	output logic [1:0] B
);

	always @(posedge clk, negedge clk)
		{A, B} <= $random % 16;

	initial begin
		repeat(1000) @(negedge clk);
		#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 [1:0] A;
	logic [1:0] B;
	logic z_ref;
	logic z_dut;

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

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

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

	top_module top_module1 (
		.A,
		.B,
		.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: Create a circuit that has two 2-bit inputs A[1:0] and B[1:0], and produces an output z. The value of z should be 1 if A = B, otherwise z should be 0.


prompt:
module top_module (
	input [2:0] sel,
	input [3:0] data0,
	input [3:0] data1,
	input [3:0] data2,
	input [3:0] data3,
	input [3:0] data4,
	input [3:0] data5,
	output reg [3:0] out
);

test:
`timescale 1 ps/1 ps
`define OK 12
`define INCORRECT 13
module reference_module (
	input [2:0] sel,
	input [3:0] data0,
	input [3:0] data1,
	input [3:0] data2,
	input [3:0] data3,
	input [3:0] data4,
	input [3:0] data5,
	output reg [3:0] out
);

	always @(*) begin
		case (sel)
			3'h0: out = data0;
			3'h1: out = data1;
			3'h2: out = data2;
			3'h3: out = data3;
			3'h4: out = data4;
			3'h5: out = data5;
			default: out = 4'b0;
		endcase
	end

endmodule

module stimulus_gen (
	input clk,
	output logic [2:0] sel,
	output logic [3:0] data0,
	output logic [3:0] data1,
	output logic [3:0] data2,
	output logic [3:0] data3,
	output logic [3:0] data4,
	output logic [3:0] data5,
	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
		data0 <= 4'ha;
		data1 <= 4'hb;
		data2 <= 4'hc;
		data3 <= 4'hd;
		data4 <= 4'he;
		data5 <= 4'hf;
		{sel} <= 3'b111;
		@(negedge clk) wavedrom_start("<b>Sel</b> chooses one of the data inputs");
			repeat(8) @(posedge clk) sel <= sel + 1;
		@(negedge clk) wavedrom_stop();

		repeat(100) @(posedge clk, negedge clk) begin
			{data0, data1, data2, data3} <= $urandom;
			{data4, data5, sel} <= $urandom;
		end
		$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 [2:0] sel;
	logic [3:0] data0;
	logic [3:0] data1;
	logic [3:0] data2;
	logic [3:0] data3;
	logic [3:0] data4;
	logic [3:0] data5;
	logic [3:0] out_ref;
	logic [3:0] out_dut;

	initial begin
		$dumpfile("wave.vcd");
		$dumpvars(1, stim1.clk, tb_mismatch ,sel,data0,data1,data2,data3,data4,data5,out_ref,out_dut );
	end

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

	stimulus_gen stim1 (
		.clk,
		.* ,
		.sel,
		.data0,
		.data1,
		.data2,
		.data3,
		.data4,
		.data5 );
	reference_module good1 (
		.sel,
		.data0,
		.data1,
		.data2,
		.data3,
		.data4,
		.data5,
		.out(out_ref) );

	top_module top_module1 (
		.sel,
		.data0,
		.data1,
		.data2,
		.data3,
		.data4,
		.data5,
		.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 6-to-1 multiplexer. When sel is between 0 and 5, choose the corresponding data input. Otherwise, output 0. The data inputs and outputs are all 4 bits wide.


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

canonical_solution:
	assign q = (a|b) & (c|d);

endmodule

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

	assign q = (a|b) & (c|d);

endmodule

module stimulus_gen (
	input clk,
	output logic 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
		{a,b,c,d} <= 0;
		@(negedge clk) wavedrom_start("Unknown circuit");
			@(posedge clk) {a,b,c,d} <= 0;
			repeat(18) @(posedge clk, negedge clk) {a,b,c,d} <= {a,b,c,d} + 1;
		wavedrom_stop();

		repeat(100) @(posedge clk, negedge clk)
			{a,b,c,d} <= $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 a;
	logic b;
	logic c;
	logic d;
	logic q_ref;
	logic q_dut;

	initial begin
		$dumpfile("wave.vcd");
		$dumpvars(1, stim1.clk, tb_mismatch ,a,b,c,d,q_ref,q_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,
		.q(q_ref) );

	top_module top_module1 (
		.a,
		.b,
		.c,
		.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


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
);

	always @(posedge clk, negedge clk)
		{x, y} <= $random % 4;

	initial begin
		repeat(100) @(negedge clk);
		#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

detail_description:
Module A implements the boolean function z = (x^y) & x.

// Module B can be described by the following simulation waveform:

// time            x               y               z
// 0ns             0               0               1
// 5ns             0               0               1
// 10ns            0               0               1
// 15ns            0               0               1
// 20ns            0               0               1
// 25ns            1               0               0
// 30ns            1               0               0
// 35ns            0               1               0
// 40ns            0               1               0
// 45ns            1               1               1
// 50ns            1               1               1
// 55ns            0               0               1
// 60ns            0               1               0
// 65ns            0               1               0
// 70ns            1               1               1
// 75ns            0               1               0
// 80ns            0               1               0
// 85ns            0               1               0
// 90ns            1               0               0

// Now consider a top-level that uses two A submodules and two B submodules. The first input of all four submodules is connect to input 'x', and the second input of all four submodules is connected to 'y'. The output of the first A submodule is connected to a two-input OR, along with the output of the first B submodule. The second pair of A and B submodules is similarly connected to an AND gate. The output of the OR and the AND is connected to an XOR, whose output is 'z'.

// Implement this circuit in Verilog.


prompt:
module top_module(
	input clk,
	input a,
	input b,
	output out_assign,
	output reg out_always_comb,
	output reg out_always_ff
);

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

	assign out_assign = a ^ b;
	always @(*) out_always_comb = a ^ b;
	always @(posedge clk) out_always_ff <= 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("XOR gate");
		repeat(10) @(posedge clk)
			{a,b} <= count++;
		wavedrom_stop();

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

		#1 $finish;
	end

endmodule

module tb();

	typedef struct packed {
		int errors;
		int errortime;
		int errors_out_assign;
		int errortime_out_assign;
		int errors_out_always_comb;
		int errortime_out_always_comb;
		int errors_out_always_ff;
		int errortime_out_always_ff;

		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_always_comb_ref;
	logic out_always_comb_dut;
	logic out_always_ff_ref;
	logic out_always_ff_dut;

	initial begin
		$dumpfile("wave.vcd");
		$dumpvars(1, stim1.clk, tb_mismatch ,clk,a,b,out_assign_ref,out_assign_dut,out_always_comb_ref,out_always_comb_dut,out_always_ff_ref,out_always_ff_dut );
	end

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

	stimulus_gen stim1 (
		.clk,
		.* ,
		.a,
		.b );
	reference_module good1 (
		.clk,
		.a,
		.b,
		.out_assign(out_assign_ref),
		.out_always_comb(out_always_comb_ref),
		.out_always_ff(out_always_ff_ref) );

	top_module top_module1 (
		.clk,
		.a,
		.b,
		.out_assign(out_assign_dut),
		.out_always_comb(out_always_comb_dut),
		.out_always_ff(out_always_ff_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_always_comb) $display("Hint: Output '%s' has %0d mismatches. First mismatch occurred at time %0d.", "out_always_comb", stats1.errors_out_always_comb, stats1.errortime_out_always_comb);
		else $display("Hint: Output '%s' has no mismatches.", "out_always_comb");
		if (stats1.errors_out_always_ff) $display("Hint: Output '%s' has %0d mismatches. First mismatch occurred at time %0d.", "out_always_ff", stats1.errors_out_always_ff, stats1.errortime_out_always_ff);
		else $display("Hint: Output '%s' has no mismatches.", "out_always_ff");

		$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_always_comb_ref, out_always_ff_ref } === ( { out_assign_ref, out_always_comb_ref, out_always_ff_ref } ^ { out_assign_dut, out_always_comb_dut, out_always_ff_dut } ^ { out_assign_ref, out_always_comb_ref, out_always_ff_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_always_comb_ref !== ( out_always_comb_ref ^ out_always_comb_dut ^ out_always_comb_ref ))
		begin if (stats1.errors_out_always_comb == 0) stats1.errortime_out_always_comb = $time;
			stats1.errors_out_always_comb = stats1.errors_out_always_comb+1'b1; end
		if (out_always_ff_ref !== ( out_always_ff_ref ^ out_always_ff_dut ^ out_always_ff_ref ))
		begin if (stats1.errors_out_always_ff == 0) stats1.errortime_out_always_ff = $time;
			stats1.errors_out_always_ff = stats1.errors_out_always_ff+1'b1; end

	end
endmodule

detail_description: Build an XOR gate three ways, using an assign statement (output out_assign), a combinational always block (output out_always_comb), and a clocked always block (output out_always_ff). Note that the clocked always block produces a different circuit from the other two: There is a flip-flop so the output is delayed.


prompt:
module top_module(
	input clk,
	input L,
	input q_in,
	input r_in,
	output reg Q);

test:
`timescale 1 ps/1 ps
`define OK 12
`define INCORRECT 13
/*
	Midterm 2015 Question 5a. Build a flip-flop with a 2-to-1 mux before it.
*/
module reference_module(
	input clk,
	input L,
	input q_in,
	input r_in,
	output reg Q);

	initial Q=0;
	always @(posedge clk)
		Q <= L ? r_in : q_in;

endmodule

module stimulus_gen (
	input clk,
	output logic L,
	output logic r_in,
	output logic q_in
);

	always @(posedge clk, negedge clk)
		{L, r_in, q_in} <= $random % 8;

	initial begin
		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 L;
	logic q_in;
	logic r_in;
	logic Q_ref;
	logic Q_dut;

	initial begin
		$dumpfile("wave.vcd");
		$dumpvars(1, stim1.clk, tb_mismatch ,clk,L,q_in,r_in,Q_ref,Q_dut );
	end

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

	stimulus_gen stim1 (
		.clk,
		.* ,
		.L,
		.q_in,
		.r_in );
	reference_module good1 (
		.clk,
		.L,
		.q_in,
		.r_in,
		.Q(Q_ref) );

	top_module top_module1 (
		.clk,
		.L,
		.q_in,
		.r_in,
		.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:
Consider this Verilog module "full_module":

// module full_module (
//     input [2:0] r,
//     input L,
//     input clk,
//     output reg [2:0] q
);

// always @(posedge clk) begin
//     if (L) begin
//         q <= r;
//     end else begin
//         q <= {q[1] ^ q[2], q[0], q[2]};
//     end
// end

// endmodule

// You want to create a hierarchical Verilog design where a flipflop and 2-1 multiplexer are in a submodule, and that submodule is instantiated three times in this code. Create the submodule called "top_module".


prompt:
module top_module (
	input [3:0] x,
	input [3:0] y,
	output [4:0] sum
);

canonical_solution:
	assign sum = x+y;
endmodule

test:
`timescale 1 ps/1 ps
`define OK 12
`define INCORRECT 13
module reference_module (
	input [3:0] x,
	input [3:0] y,
	output [4:0] sum
);

	assign sum = x+y;
endmodule

module stimulus_gen (
	input clk,
	output logic [3:0] x,y
);

	initial begin
		repeat(100) @(posedge clk, negedge clk) begin
			{x,y} <= $random;
		end

		#1 $finish;
	end

endmodule

module tb();

	typedef struct packed {
		int errors;
		int errortime;
		int errors_sum;
		int errortime_sum;

		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] x;
	logic [3:0] y;
	logic [4:0] sum_ref;
	logic [4:0] sum_dut;

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

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

	stimulus_gen stim1 (
		.clk,
		.* ,
		.x,
		.y );
	reference_module good1 (
		.x,
		.y,
		.sum(sum_ref) );

	top_module top_module1 (
		.x,
		.y,
		.sum(sum_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_sum) $display("Hint: Output '%s' has %0d mismatches. First mismatch occurred at time %0d.", "sum", stats1.errors_sum, stats1.errortime_sum);
		else $display("Hint: Output '%s' has no mismatches.", "sum");

		$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 = ( { sum_ref } === ( { sum_ref } ^ { sum_dut } ^ { sum_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 (sum_ref !== ( sum_ref ^ sum_dut ^ sum_ref ))
		begin if (stats1.errors_sum == 0) stats1.errortime_sum = $time;
			stats1.errors_sum = stats1.errors_sum+1'b1; end

	end
endmodule

detail_description: Implement a 4-bit adder with full adders. The output sum should include the overflow bit.


task_id: norgate

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("NOR 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 a NOR gate.


prompt:
module top_module (
	input in,
	input [1:0] state,
	output reg [1:0] next_state,
	output out
);

test:
`timescale 1 ps/1 ps
`define OK 12
`define INCORRECT 13
module reference_module (
	input in,
	input [1:0] state,
	output reg [1:0] next_state,
	output out
);
	parameter A=0, B=1, C=2, D=3;

    always_comb begin
		case (state)
			A: next_state = in ? B : A;
			B: next_state = in ? B : C;
			C: next_state = in ? D : A;
			D: next_state = in ? B : C;
		endcase
    end

	assign out = (state==D);

endmodule

module stimulus_gen (
	input clk,
	output logic in,
	output logic [1:0] state
);

	initial begin
		repeat(100) @(posedge clk, negedge clk) begin
			in <= $random;
			state <= $random;
		end

		#1 $finish;
	end

endmodule

module tb();

	typedef struct packed {
		int errors;
		int errortime;
		int errors_next_state;
		int errortime_next_state;
		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 in;
	logic [1:0] state;
	logic [1:0] next_state_ref;
	logic [1:0] next_state_dut;
	logic out_ref;
	logic out_dut;

	initial begin
		$dumpfile("wave.vcd");
		$dumpvars(1, stim1.clk, tb_mismatch ,in,state,next_state_ref,next_state_dut,out_ref,out_dut );
	end

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

	stimulus_gen stim1 (
		.clk,
		.* ,
		.in,
		.state );
	reference_module good1 (
		.in,
		.state,
		.next_state(next_state_ref),
		.out(out_ref) );

	top_module top_module1 (
		.in,
		.state,
		.next_state(next_state_dut),
		.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_next_state) $display("Hint: Output '%s' has %0d mismatches. First mismatch occurred at time %0d.", "next_state", stats1.errors_next_state, stats1.errortime_next_state);
		else $display("Hint: Output '%s' has no mismatches.", "next_state");
		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 = ( { next_state_ref, out_ref } === ( { next_state_ref, out_ref } ^ { next_state_dut, out_dut } ^ { next_state_ref, 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 (next_state_ref !== ( next_state_ref ^ next_state_dut ^ next_state_ref ))
		begin if (stats1.errors_next_state == 0) stats1.errortime_next_state = $time;
			stats1.errors_next_state = stats1.errors_next_state+1'b1; 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:
The following is the state transition table for a Moore state machine with one input, one output, and four states. Use the following state encoding: A=2'b00, B=2'b01, C=2'b10, D=2'b11.Implement only the state transition logic and output logic (the combinational logic portion) for this state machine. Given the current state (state), compute the next_state and output (out) based on the state transition table.
// State | Next state in=0, Next state in=1 | Output
// A | A, B | 0
// B | C, B | 0
// C | A, D | 0
// D | C, B | 1


prompt:
module top_module (
	input clk,
	input in,
	input reset,
	output [7:0] out_byte,
	output done
);

test:
`timescale 1 ps/1 ps
`define OK 12
`define INCORRECT 13
module reference_module (
	input clk,
	input in,
	input reset,
	output [7:0] out_byte,
	output done
);
	parameter B0=0, B1=1, B2=2, B3=3, B4=4, B5=5, B6=6, B7=7, START=8, STOP=9, DONE=10, ERR=11;
	reg [3:0] state;
	reg [3:0] next;

    reg [9:0] byte_r;

    always_comb begin
		case (state)
			START: next = in ? START : B0;	// start bit is 0
			B0: next = B1;
			B1: next = B2;
			B2: next = B3;
			B3: next = B4;
			B4: next = B5;
			B5: next = B6;
			B6: next = B7;
			B7: next = STOP;
			STOP: next = in ? DONE : ERR;  // stop bit is 1. Idle state is 1.
			DONE: next = in ? START : B0;
			ERR: next = in ? START : ERR;
		endcase
    end

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

	always @(posedge clk) begin
		byte_r <= {in, byte_r[9:1]};
	end

	assign done = (state==DONE);
	assign out_byte = done ? byte_r[8:1] : 8'hx;

endmodule

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

	initial begin
		reset <= 1;
		in <= 1;
		@(posedge clk);
		reset <= 0;
		in <= 0;
		repeat(9) @(posedge clk);
		in <= 1;
		@(posedge clk);
		in <= 0;
		repeat(9) @(posedge clk);
		in <= 1;
		@(posedge clk);
		in <= 0;
		repeat(10) @(posedge clk);
		in <= 1;
		@(posedge clk);
		in <= 0;
		repeat(10) @(posedge clk);
		in <= 1;
		@(posedge clk);
		in <= 0;
		repeat(9) @(posedge clk);
		in <= 1;
		@(posedge clk);

		repeat(800) @(posedge clk, negedge clk) begin
			in <= $random;
			reset <= !($random & 31);
		end

		#1 $finish;
	end

endmodule

module tb();

	typedef struct packed {
		int errors;
		int errortime;
		int errors_out_byte;
		int errortime_out_byte;
		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 in;
	logic reset;
	logic [7:0] out_byte_ref;
	logic [7:0] out_byte_dut;
	logic done_ref;
	logic done_dut;

	initial begin
		$dumpfile("wave.vcd");
		$dumpvars(1, stim1.clk, tb_mismatch ,clk,in,reset,out_byte_ref,out_byte_dut,done_ref,done_dut );
	end

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

	stimulus_gen stim1 (
		.clk,
		.* ,
		.in,
		.reset );
	reference_module good1 (
		.clk,
		.in,
		.reset,
		.out_byte(out_byte_ref),
		.done(done_ref) );

	top_module top_module1 (
		.clk,
		.in,
		.reset,
		.out_byte(out_byte_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_out_byte) $display("Hint: Output '%s' has %0d mismatches. First mismatch occurred at time %0d.", "out_byte", stats1.errors_out_byte, stats1.errortime_out_byte);
		else $display("Hint: Output '%s' has no mismatches.", "out_byte");
		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 = ( { out_byte_ref, done_ref } === ( { out_byte_ref, done_ref } ^ { out_byte_dut, done_dut } ^ { out_byte_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 (out_byte_ref !== ( out_byte_ref ^ out_byte_dut ^ out_byte_ref ))
		begin if (stats1.errors_out_byte == 0) stats1.errortime_out_byte = $time;
			stats1.errors_out_byte = stats1.errors_out_byte+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: In many (older) serial communications protocols, each data byte is sent along with a start bit and a stop bit, to help the receiver delimit bytes from the stream of bits. One common scheme is to use one start bit (0), 8 data bits, and 1 stop bit (1). The line is also at logic 1 when nothing is being transmitted (idle). Design a finite state machine that will identify when bytes have been correctly received when given a stream of bits. It needs to identify the start bit, wait for all 8 data bits, then verify that the stop bit was correct. The module will also output the correctly-received data byte. out_byte needs to be valid when done is 1, and is don't-care otherwise.If the stop bit does not appear when expected, the FSM must wait until it finds a stop bit before attempting to receive the next byte. Include a active-high synchronous reset. Note that the serial protocol sends the least significant bit first. It should assert done each time it finds a stop bit.


prompt:
module top_module (
	input [4:0] a,
	input [4:0] b,
	input [4:0] c,
	input [4:0] d,
	input [4:0] e,
	input [4:0] f,
	output [7:0] w,
	output [7:0] x,
	output [7:0] y,
	output [7:0] z
);

test:
`timescale 1 ps/1 ps
`define OK 12
`define INCORRECT 13
module reference_module (
	input [4:0] a,
	input [4:0] b,
	input [4:0] c,
	input [4:0] d,
	input [4:0] e,
	input [4:0] f,
	output [7:0] w,
	output [7:0] x,
	output [7:0] y,
	output [7:0] z
);

	assign { w,x,y,z} = {a,b,c,d,e,f,2'b11};

endmodule

module stimulus_gen (
	input clk,
	output logic [4:0] a,b,c,d,e,f,
	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
		wavedrom_start("");
		@(posedge clk) {a,b,c,d,e,f} <= '0;
		@(posedge clk) {a,b,c,d,e,f} <= 1;
		@(posedge clk) {a,b,c,d,e,f} <= 2;
		@(posedge clk) {a,b,c,d,e,f} <= 4;
		@(posedge clk) {a,b,c,d,e,f} <= 8;
		@(posedge clk) {a,b,c,d,e,f} <= 'h10;
		@(posedge clk) {a,b,c,d,e,f} <= 'h20;
		@(posedge clk) {a,b,c,d,e,f} <= 'h40;
		@(posedge clk) {a,b,c,d,e,f} <= 'h80;
		@(posedge clk) {a,b,c,d,e,f} <= 'h100;
		@(posedge clk) {a,b,c,d,e,f} <= 'h200;
		@(posedge clk) {a,b,c,d,e,f} <= 'h400;
		@(posedge clk) {a,b,c,d,e,f} <= {5'h1f, 5'h0, 5'h1f, 5'h0, 5'h1f, 5'h0};
		@(negedge clk);
		wavedrom_stop();
		repeat(100) @(posedge clk, negedge clk)
			{a,b,c,d,e,f} <= $random;
		$finish;
	end

endmodule

module tb();

	typedef struct packed {
		int errors;
		int errortime;
		int errors_w;
		int errortime_w;
		int errors_x;
		int errortime_x;
		int errors_y;
		int errortime_y;
		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 [4:0] a;
	logic [4:0] b;
	logic [4:0] c;
	logic [4:0] d;
	logic [4:0] e;
	logic [4:0] f;
	logic [7:0] w_ref;
	logic [7:0] w_dut;
	logic [7:0] x_ref;
	logic [7:0] x_dut;
	logic [7:0] y_ref;
	logic [7:0] y_dut;
	logic [7:0] z_ref;
	logic [7:0] z_dut;

	initial begin
		$dumpfile("wave.vcd");
		$dumpvars(1, stim1.clk, tb_mismatch ,a,b,c,d,e,f,w_ref,w_dut,x_ref,x_dut,y_ref,y_dut,z_ref,z_dut );
	end

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

	stimulus_gen stim1 (
		.clk,
		.* ,
		.a,
		.b,
		.c,
		.d,
		.e,
		.f );
	reference_module good1 (
		.a,
		.b,
		.c,
		.d,
		.e,
		.f,
		.w(w_ref),
		.x(x_ref),
		.y(y_ref),
		.z(z_ref) );

	top_module top_module1 (
		.a,
		.b,
		.c,
		.d,
		.e,
		.f,
		.w(w_dut),
		.x(x_dut),
		.y(y_dut),
		.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_w) $display("Hint: Output '%s' has %0d mismatches. First mismatch occurred at time %0d.", "w", stats1.errors_w, stats1.errortime_w);
		else $display("Hint: Output '%s' has no mismatches.", "w");
		if (stats1.errors_x) $display("Hint: Output '%s' has %0d mismatches. First mismatch occurred at time %0d.", "x", stats1.errors_x, stats1.errortime_x);
		else $display("Hint: Output '%s' has no mismatches.", "x");
		if (stats1.errors_y) $display("Hint: Output '%s' has %0d mismatches. First mismatch occurred at time %0d.", "y", stats1.errors_y, stats1.errortime_y);
		else $display("Hint: Output '%s' has no mismatches.", "y");
		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 = ( { w_ref, x_ref, y_ref, z_ref } === ( { w_ref, x_ref, y_ref, z_ref } ^ { w_dut, x_dut, y_dut, z_dut } ^ { w_ref, x_ref, y_ref, 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 (w_ref !== ( w_ref ^ w_dut ^ w_ref ))
		begin if (stats1.errors_w == 0) stats1.errortime_w = $time;
			stats1.errors_w = stats1.errors_w+1'b1; end
		if (x_ref !== ( x_ref ^ x_dut ^ x_ref ))
		begin if (stats1.errors_x == 0) stats1.errortime_x = $time;
			stats1.errors_x = stats1.errors_x+1'b1; end
		if (y_ref !== ( y_ref ^ y_dut ^ y_ref ))
		begin if (stats1.errors_y == 0) stats1.errortime_y = $time;
			stats1.errors_y = stats1.errors_y+1'b1; 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 several input vectors, concatenate them together then split them up into several output vectors. There are six 5-bit input vectors: a, b, c, d, e, and f, for a total of 30 bits of input. There are four 8-bit output vectors: w, x, y, and z, for 32 bits of output. The output should be a concatenation of the input vectors followed by two 1 bits (the two 1 bits should be in the LSB positions).


prompt:
module top_module
(
    input clk,
    input areset,
    input predict_valid,
    input predict_taken,
    output logic [31:0] predict_history,

    input train_mispredicted,
    input train_taken,
    input [31:0] train_history
);

test:
`timescale 1 ps/1 ps
`define OK 12
`define INCORRECT 13
module reference_module
(
    input clk,
    input areset,
    input predict_valid,
    input predict_taken,
    output logic [31:0] predict_history,

    input train_mispredicted,
    input train_taken,
    input [31:0] train_history
);
    always@(posedge clk, posedge areset)
		if (areset) begin
			predict_history = 0;
        end	else begin
			if (train_mispredicted)
				predict_history <= {train_history, train_taken};
			else if (predict_valid)
				predict_history <= {predict_history, predict_taken};
		end
endmodule

module stimulus_gen
(
	input clk,
	output logic areset,

	output logic predict_valid,
	output predict_taken,

	output logic train_mispredicted,
	output train_taken,
	output [31:0] train_history,

	input tb_match,
	output reg[511:0] wavedrom_title,
	output reg wavedrom_enable,
	output int wavedrom_hide_after_time
);

// 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 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

	assign areset = reset;
	logic predict_taken_r;
	assign predict_taken = predict_valid ? predict_taken_r : 1'bx;

	logic train_taken_r;
	logic [31:0] train_history_r;
	assign train_taken = train_mispredicted ? train_taken_r : 1'bx;
	assign train_history = train_mispredicted ? train_history_r : 32'hx;

	initial begin
		@(posedge clk) reset <= 1;
		@(posedge clk) reset <= 0;
		predict_taken_r <= 1;
		predict_valid <= 1;
		train_mispredicted <= 0;
		train_history_r <= 32'h5;
		train_taken_r <= 1;

		wavedrom_start("Asynchronous reset");
			reset_test(1); // Test for asynchronous reset
		wavedrom_stop();
		@(posedge clk) reset <= 1;
		predict_valid <= 0;

		wavedrom_start("Predictions: Shift in");
		repeat(2) @(posedge clk) {predict_valid, predict_taken_r} <= {$urandom};
		reset <= 0;
		predict_valid <= 1;
		repeat(6) @(posedge clk) {predict_taken_r} <= {$urandom};
		predict_valid <= 0;
		repeat(3) @(posedge clk) {predict_taken_r} <= {$urandom};
		predict_valid <= 1;
		train_mispredicted <= 1;
		@(posedge clk) train_mispredicted <= 0;
		repeat(6) @(posedge clk) {predict_taken_r} <= {$urandom};
		wavedrom_stop();

		repeat(2000) @(posedge clk,negedge clk) begin
			{predict_valid, predict_taken_r, train_taken_r} <= {$urandom};
			train_history_r <= $urandom;
			train_mispredicted <= !($urandom_range(0,31));
		end

		#1 $finish;
	end

endmodule
module tb();

	typedef struct packed {
		int errors;
		int errortime;
		int errors_predict_history;
		int errortime_predict_history;

		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 predict_valid;
	logic predict_taken;
	logic train_mispredicted;
	logic train_taken;
	logic [31:0] train_history;
	logic [31:0] predict_history_ref;
	logic [31:0] predict_history_dut;

	initial begin
		$dumpfile("wave.vcd");
		$dumpvars(1, stim1.clk, tb_mismatch ,clk,areset,predict_valid,predict_taken,train_mispredicted,train_taken,train_history,predict_history_ref,predict_history_dut );
	end

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

	stimulus_gen stim1 (
		.clk,
		.* ,
		.areset,
		.predict_valid,
		.predict_taken,
		.train_mispredicted,
		.train_taken,
		.train_history );
	reference_module good1 (
		.clk,
		.areset,
		.predict_valid,
		.predict_taken,
		.train_mispredicted,
		.train_taken,
		.train_history,
		.predict_history(predict_history_ref) );

	top_module top_module1 (
		.clk,
		.areset,
		.predict_valid,
		.predict_taken,
		.train_mispredicted,
		.train_taken,
		.train_history,
		.predict_history(predict_history_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_predict_history) $display("Hint: Output '%s' has %0d mismatches. First mismatch occurred at time %0d.", "predict_history", stats1.errors_predict_history, stats1.errortime_predict_history);
		else $display("Hint: Output '%s' has no mismatches.", "predict_history");

		$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 = ( { predict_history_ref } === ( { predict_history_ref } ^ { predict_history_dut } ^ { predict_history_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 (predict_history_ref !== ( predict_history_ref ^ predict_history_dut ^ predict_history_ref ))
		begin if (stats1.errors_predict_history == 0) stats1.errortime_predict_history = $time;
			stats1.errors_predict_history = stats1.errors_predict_history+1'b1; end

	end
endmodule

detail_description: Build a 32-bit global history shift register, including support for rolling back state in response to a pipeline flush caused by a branch misprediction. When a branch prediction is made (predict_valid = 1), shift in predict_taken from the LSB side to update the branch history for the predicted branch. (predict_history[0] is the direction of the youngest branch.) When a branch misprediction occurs (train_mispredicted = 1), load the branch history register with the history after the completion of the mispredicted branch. This is the history before the mispredicted branch (train_history) concatenated with the actual result of the branch (train_taken). If both a prediction and misprediction occur at the same time, the misprediction takes precedence, because the pipeline flush will also flush out the branch that is currently making a prediction. predict_history is the value of the branch history register. areset is a positive edge triggered asynchronous reset that resets the history counter to zero.


prompt:
module top_module (
	input do_sub,
	input [7:0] a,
	input [7:0] b,
	output reg [7:0] out,
	output reg result_is_zero
);

test:
`timescale 1 ps/1 ps
`define OK 12
`define INCORRECT 13
module reference_module (
	input do_sub,
	input [7:0] a,
	input [7:0] b,
	output reg [7:0] out,
	output reg result_is_zero
);

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

endmodule

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

// 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
		{a, b} <= 16'haabb;
		do_sub <= 0;
		@(negedge clk) wavedrom_start("");
			@(posedge clk, negedge clk) do_sub <= 0;
			@(posedge clk, negedge clk) do_sub <= 0;
			@(posedge clk, negedge clk) do_sub <= 1;
			@(posedge clk, negedge clk) do_sub <= 1;

			@(posedge clk, negedge clk) {a, b} <= 16'h0303; do_sub <= 1'b0;
			@(posedge clk, negedge clk) do_sub <= 0;
			@(posedge clk, negedge clk) do_sub <= 1;
			@(posedge clk, negedge clk) {a, b} <= 16'h0304; do_sub <= 1'b0;
			@(posedge clk, negedge clk) do_sub <= 0;
			@(posedge clk, negedge clk) do_sub <= 1;
			@(posedge clk, negedge clk) {a, b} <= 16'hfd03; do_sub <= 1'b0;
			@(posedge clk, negedge clk) do_sub <= 0;
			@(posedge clk, negedge clk) do_sub <= 1;
			@(posedge clk, negedge clk) {a, b} <= 16'hfd04; do_sub <= 1'b0;
			@(posedge clk, negedge clk) do_sub <= 0;
			@(posedge clk, negedge clk) do_sub <= 1;
		wavedrom_stop();

		repeat(100) @(posedge clk, negedge clk) begin
			{a,b, do_sub} <= $urandom;
		end

		$finish;
	end

endmodule

module tb();

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

		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 do_sub;
	logic [7:0] a;
	logic [7:0] b;
	logic [7:0] out_ref;
	logic [7:0] out_dut;
	logic result_is_zero_ref;
	logic result_is_zero_dut;

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

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

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

	top_module top_module1 (
		.do_sub,
		.a,
		.b,
		.out(out_dut),
		.result_is_zero(result_is_zero_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");
		if (stats1.errors_result_is_zero) $display("Hint: Output '%s' has %0d mismatches. First mismatch occurred at time %0d.", "result_is_zero", stats1.errors_result_is_zero, stats1.errortime_result_is_zero);
		else $display("Hint: Output '%s' has no mismatches.", "result_is_zero");

		$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, result_is_zero_ref } === ( { out_ref, result_is_zero_ref } ^ { out_dut, result_is_zero_dut } ^ { out_ref, result_is_zero_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
		if (result_is_zero_ref !== ( result_is_zero_ref ^ result_is_zero_dut ^ result_is_zero_ref ))
		begin if (stats1.errors_result_is_zero == 0) stats1.errortime_result_is_zero = $time;
			stats1.errors_result_is_zero = stats1.errors_result_is_zero+1'b1; end

	end
endmodule

detail_description:
The following adder-subtractor with zero flag doesn't work. Fix the bug(s).

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

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

//         if (~out)
//             result_is_zero = 1;
//     end

// endmodule


prompt:
module top_module (
	input x3,
	input x2,
	input x1,
	output f
);

test:
`timescale 1 ps/1 ps
`define OK 12
`define INCORRECT 13
module reference_module (
	input x3,
	input x2,
	input x1,
	output f
);

	assign f = ( ~x3 & x2 & ~x1 ) |
				( ~x3 & x2 & x1 ) |
				( x3 & ~x2 & x1 ) |
				( x3 & x2 & x1 ) ;

endmodule

module stimulus_gen (
	input clk,
	output reg x3, x2, x1,
	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
		{x3, x2, x1} <= 3'h7;
		@(negedge clk) wavedrom_start("All 8 input combinations");
		repeat(8) @(posedge clk) {x3, x2, x1} <= {x3, x2, x1} + 1'b1;
		@(negedge clk) wavedrom_stop();
		repeat(40) @(posedge clk, negedge clk);
		{x3, x2, x1} <= $random;
		$finish;
	end

endmodule

module tb();

	typedef struct packed {
		int errors;
		int errortime;
		int errors_f;
		int errortime_f;

		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 x3;
	logic x2;
	logic x1;
	logic f_ref;
	logic f_dut;

	initial begin
		$dumpfile("wave.vcd");
		$dumpvars(1, stim1.clk, tb_mismatch ,x3,x2,x1,f_ref,f_dut );
	end

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

	stimulus_gen stim1 (
		.clk,
		.* ,
		.x3,
		.x2,
		.x1 );
	reference_module good1 (
		.x3,
		.x2,
		.x1,
		.f(f_ref) );

	top_module top_module1 (
		.x3,
		.x2,
		.x1,
		.f(f_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_f) $display("Hint: Output '%s' has %0d mismatches. First mismatch occurred at time %0d.", "f", stats1.errors_f, stats1.errortime_f);
		else $display("Hint: Output '%s' has no mismatches.", "f");

		$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 = ( { f_ref } === ( { f_ref } ^ { f_dut } ^ { f_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 (f_ref !== ( f_ref ^ f_dut ^ f_ref ))
		begin if (stats1.errors_f == 0) stats1.errortime_f = $time;
			stats1.errors_f = stats1.errors_f+1'b1; end

	end
endmodule


prompt:
module top_module (
	input [3:0] a,
	input [3:0] b,
	input [3:0] c,
	input [3:0] d,
	input [3:0] e,
	output reg [3:0] q
);

test:
`timescale 1 ps/1 ps
`define OK 12
`define INCORRECT 13
module reference_module (
	input [3:0] a,
	input [3:0] b,
	input [3:0] c,
	input [3:0] d,
	input [3:0] e,
	output reg [3:0] q
);

	always @(*)
		case (c)
			0: q = b;
			1: q = e;
			2: q = a;
			3: q = d;
			default: q = 4'hf;
		endcase

endmodule

module stimulus_gen (
	input clk,
	output logic [3:0] a,b,c,d,e,
	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,b,c,d,e} <= {20'hab0de};
			repeat(18) @(posedge clk, negedge clk) c <= c + 1;
		wavedrom_stop();

		@(negedge clk) wavedrom_start("Unknown circuit");
			@(posedge clk) {a,b,c,d,e} <= {20'h12034};
			repeat(8) @(posedge clk, negedge clk) c <= c + 1;
			@(posedge clk) {a,b,c,d,e} <= {20'h56078};
			repeat(8) @(posedge clk, negedge clk) c <= c + 1;
		wavedrom_stop();

		repeat(100) @(posedge clk, negedge clk)
			{a,b,c,d,e} <= $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 [3:0] a;
	logic [3:0] b;
	logic [3:0] c;
	logic [3:0] d;
	logic [3:0] e;
	logic [3:0] q_ref;
	logic [3:0] q_dut;

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

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

	stimulus_gen stim1 (
		.clk,
		.* ,
		.a,
		.b,
		.c,
		.d,
		.e );
	reference_module good1 (
		.a,
		.b,
		.c,
		.d,
		.e,
		.q(q_ref) );

	top_module top_module1 (
		.a,
		.b,
		.c,
		.d,
		.e,
		.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               b               c               d               e               q
// 0ns             x               x               x               x               x               x
// 5ns             x               x               x               x               x               x
// 10ns            x               x               x               x               x               x
// 15ns            a               b               0               d               e               b
// 20ns            a               b               1               d               e               e
// 25ns            a               b               2               d               e               a
// 30ns            a               b               3               d               e               d
// 35ns            a               b               4               d               e               f
// 40ns            a               b               5               d               e               f
// 45ns            a               b               6               d               e               f
// 50ns            a               b               7               d               e               f
// 55ns            a               b               8               d               e               f
// 60ns            a               b               9               d               e               f
// 65ns            a               b               a               d               e               f
// 70ns            a               b               b               d               e               f
// 75ns            a               b               c               d               e               f
// 80ns            a               b               d               d               e               f
// 85ns            a               b               e               d               e               f
// 90ns            a               b               f               d               e               f


prompt:
module top_module (
	input [4:1] x,
	output logic f
);

test:
`timescale 1 ps/1 ps
`define OK 12
`define INCORRECT 13
module reference_module (
	input [4:1] x,
	output logic f
);

	always_comb begin
		case (x)
			4'h0: f = 1'bx;
			4'h1: f = 1'bx;
			4'h2: f = 0;
			4'h3: f = 1'bx;
			4'h4: f = 1;
			4'h5: f = 1'bx;
			4'h6: f = 1;
			4'h7: f = 0;
			4'h8: f = 0;
			4'h9: f = 0;
			4'ha: f = 1'bx;
			4'hb: f = 1;
			4'hc: f = 1;
			4'hd: f = 1'bx;
			4'he: f = 1;
			4'hf: f = 1'bx;
		endcase
	end

endmodule

module stimulus_gen (
	input clk,
	output logic [4:1] x
);

	initial begin
		repeat(100) @(posedge clk, negedge clk) begin
			x <= $random;
		end

		#1 $finish;
	end

endmodule

module tb();

	typedef struct packed {
		int errors;
		int errortime;
		int errors_f;
		int errortime_f;

		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 [4:1] x;
	logic f_ref;
	logic f_dut;

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

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

	stimulus_gen stim1 (
		.clk,
		.* ,
		.x );
	reference_module good1 (
		.x,
		.f(f_ref) );

	top_module top_module1 (
		.x,
		.f(f_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_f) $display("Hint: Output '%s' has %0d mismatches. First mismatch occurred at time %0d.", "f", stats1.errors_f, stats1.errortime_f);
		else $display("Hint: Output '%s' has no mismatches.", "f");

		$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 = ( { f_ref } === ( { f_ref } ^ { f_dut } ^ { f_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 (f_ref !== ( f_ref ^ f_dut ^ f_ref ))
		begin if (stats1.errors_f == 0) stats1.errortime_f = $time;
			stats1.errors_f = stats1.errors_f+1'b1; end

	end
endmodule

detail_description:
Consider the function f shown in the Karnaugh map below. d is don't-care, which means you may choose to output whatever value is convenient. Implement this function.
//        x[1]x[2]
// x[3]x[4]   00 01 11 10
//  00 | d | 0 | d | d |
//  01 | 0 | d | 1 | 0 |
//  11 | 1 | 1 | d | d |
//  10 | 1 | 1 | 0 | d |


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

canonical_solution:
	assign out = in1 & ~in2;
endmodule

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

	assign out = in1 & ~in2;
endmodule

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

	initial begin
		repeat(100) @(posedge clk, negedge clk) begin
			{in1, in2} <= $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 out_ref;
	logic out_dut;

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

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

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

	top_module top_module1 (
		.in1,
		.in2,
		.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 the following circuit in Verilog. Two inputs (in1 and in2) go to an AND gate, but the in2 input to the AND gate has a bubble. The output of the AND gate is connected to 'out'.


task_id: gshare

prompt:
module top_module(
	input clk,
	input areset,

	input predict_valid,
	input [6:0] predict_pc,
	output predict_taken,
	output [6:0] predict_history,

	input train_valid,
	input train_taken,
	input train_mispredicted,
	input [6:0] train_history,
	input [6:0] train_pc
);

test:
`timescale 1 ps/1 ps
`define OK 12
`define INCORRECT 13
module reference_module(
	input clk,
	input areset,

	input predict_valid,
	input [6:0] predict_pc,
	output predict_taken,
	output [6:0] predict_history,

	input train_valid,
	input train_taken,
	input train_mispredicted,
	input [6:0] train_history,
	input [6:0] train_pc
);
	parameter n = 7;
	logic [1:0] pht [2**n-1:0];

	parameter [1:0] SNT = 0, LNT = 1, LT = 2, ST = 3;

	logic [n-1:0] predict_history_r;
	wire [n-1:0] predict_index = predict_history_r ^ predict_pc;
	wire [n-1:0] train_index = train_history ^ train_pc;

	always@(posedge clk, posedge areset)
		if (areset) begin
			for (integer i=0; i<2**n; i=i+1)
				pht[i] = LNT;
			predict_history_r = 0;
        end	else begin
			if (predict_valid)
				predict_history_r <= {predict_history_r, predict_taken};
			if(train_valid) begin
				if(pht[train_index] < 3 && train_taken)
					pht[train_index] <= pht[train_index] + 1;
				else if(pht[train_index] > 0 && !train_taken)
					pht[train_index] <= pht[train_index] - 1;
				if (train_mispredicted)
					predict_history_r <= {train_history, train_taken};
			end
		end

	assign predict_taken = predict_valid ? pht[predict_index][1] : 1'bx;
	assign predict_history = predict_valid ? predict_history_r : {n{1'bx}};
endmodule

module stimulus_gen
#(parameter N=7)
(
	input clk,
	output logic areset,

	output logic predict_valid,
	output [N-1:0] predict_pc,

	output logic train_valid,
	output train_taken,
	output train_mispredicted,
	output [N-1:0] train_history,
	output [N-1:0] train_pc,

	input tb_match,
	output reg[511:0] wavedrom_title,
	output reg wavedrom_enable,
	output int wavedrom_hide_after_time
);

// 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 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

	assign areset = reset;

	logic [N-1:0] predict_pc_r;
	logic train_taken_r;
	logic train_mispredicted_r;
	logic [N-1:0] train_history_r;
	logic [N-1:0] train_pc_r;

	assign predict_pc = predict_valid ? predict_pc_r : {N{1'bx}};
	assign train_taken = train_valid ? train_taken_r : 1'bx;
	assign train_mispredicted = train_valid ? train_mispredicted_r : 1'bx;
	assign train_history = train_valid ? train_history_r : {N{1'bx}};
	assign train_pc = train_valid ? train_pc_r : {N{1'bx}};

	initial begin
		@(posedge clk) reset <= 1;
		@(posedge clk) reset <= 0;
		predict_valid <= 1;
		train_mispredicted_r <= 1;
		train_history_r <= 7'h7f;
		train_pc_r <= 7'h4;
		train_taken_r <= 1;
		train_valid <= 1;
		predict_valid <= 1;
		predict_pc_r <= 4;

		wavedrom_start("Asynchronous reset");
			reset_test(1); // Test for asynchronous reset
		wavedrom_stop();
		@(posedge clk) reset <= 1;
		predict_valid <= 0;

		wavedrom_start("Training entries (pc = 0xa, history = 0 and 2)");
		predict_pc_r <= 7'ha;
		predict_valid <= 1;

		train_history_r <= 7'h0;
		train_pc_r <= 7'ha;
		train_taken_r <= 1;
		train_valid <= 0;
		train_mispredicted_r <= 0;

		@(negedge clk) reset <= 0;
		@(posedge clk) train_valid <= 1;
		@(posedge clk) train_history_r <= 7'h2;
		@(posedge clk) train_valid <= 0;

		repeat(4) @(posedge clk);
		train_history_r <= 7'h0;
		train_taken_r <= 0;
		train_valid <= 1;
		@(posedge clk) train_valid <= 0;

		repeat(8) @(posedge clk);
		wavedrom_stop();

		@(posedge clk);

		wavedrom_start("History register recovery on misprediction");
		reset <= 1;
		predict_pc_r <= 7'ha;
		predict_valid <= 1;

		train_history_r <= 7'h0;
		train_pc_r <= 7'ha;
		train_taken_r <= 1;
		train_valid <= 0;
		train_mispredicted_r <= 1;

		@(negedge clk) reset <= 0;
		@(posedge clk);
		@(posedge clk) train_valid <= 1;
		@(posedge clk) train_valid <= 0;
		@(posedge clk) train_valid <= 1;
		train_history_r <= 7'h10;
		train_taken_r <= 0;
		@(posedge clk) train_valid <= 0;

		repeat(4) @(posedge clk);
		train_history_r <= 7'h0;
		train_taken_r <= 0;
		train_valid <= 1;
		@(posedge clk) train_valid <= 0;
		@(posedge clk) train_valid <= 1;
		train_history_r <= 7'h20;
		@(posedge clk) train_valid <= 0;

		repeat(3) @(posedge clk);
		wavedrom_stop();

		repeat(1000) @(posedge clk,negedge clk) begin
			{predict_valid, predict_pc_r, train_pc_r, train_taken_r, train_valid} <= {$urandom};
			train_history_r <= $urandom;
			train_mispredicted_r <= !($urandom_range(0,31));
		end

		#1 $finish;
	end

endmodule
module tb();

	typedef struct packed {
		int errors;
		int errortime;
		int errors_predict_taken;
		int errortime_predict_taken;
		int errors_predict_history;
		int errortime_predict_history;

		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 predict_valid;
	logic [6:0] predict_pc;
	logic train_valid;
	logic train_taken;
	logic train_mispredicted;
	logic [6:0] train_history;
	logic [6:0] train_pc;
	logic predict_taken_ref;
	logic predict_taken_dut;
	logic [6:0] predict_history_ref;
	logic [6:0] predict_history_dut;

	initial begin
		$dumpfile("wave.vcd");
		$dumpvars(1, stim1.clk, tb_mismatch ,clk,areset,predict_valid,predict_pc,train_valid,train_taken,train_mispredicted,train_history,train_pc,predict_taken_ref,predict_taken_dut,predict_history_ref,predict_history_dut );
	end

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

	stimulus_gen stim1 (
		.clk,
		.* ,
		.areset,
		.predict_valid,
		.predict_pc,
		.train_valid,
		.train_taken,
		.train_mispredicted,
		.train_history,
		.train_pc );
	reference_module good1 (
		.clk,
		.areset,
		.predict_valid,
		.predict_pc,
		.train_valid,
		.train_taken,
		.train_mispredicted,
		.train_history,
		.train_pc,
		.predict_taken(predict_taken_ref),
		.predict_history(predict_history_ref) );

	top_module top_module1 (
		.clk,
		.areset,
		.predict_valid,
		.predict_pc,
		.train_valid,
		.train_taken,
		.train_mispredicted,
		.train_history,
		.train_pc,
		.predict_taken(predict_taken_dut),
		.predict_history(predict_history_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_predict_taken) $display("Hint: Output '%s' has %0d mismatches. First mismatch occurred at time %0d.", "predict_taken", stats1.errors_predict_taken, stats1.errortime_predict_taken);
		else $display("Hint: Output '%s' has no mismatches.", "predict_taken");
		if (stats1.errors_predict_history) $display("Hint: Output '%s' has %0d mismatches. First mismatch occurred at time %0d.", "predict_history", stats1.errors_predict_history, stats1.errortime_predict_history);
		else $display("Hint: Output '%s' has no mismatches.", "predict_history");

		$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 = ( { predict_taken_ref, predict_history_ref } === ( { predict_taken_ref, predict_history_ref } ^ { predict_taken_dut, predict_history_dut } ^ { predict_taken_ref, predict_history_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 (predict_taken_ref !== ( predict_taken_ref ^ predict_taken_dut ^ predict_taken_ref ))
		begin if (stats1.errors_predict_taken == 0) stats1.errortime_predict_taken = $time;
			stats1.errors_predict_taken = stats1.errors_predict_taken+1'b1; end
		if (predict_history_ref !== ( predict_history_ref ^ predict_history_dut ^ predict_history_ref ))
		begin if (stats1.errors_predict_history == 0) stats1.errortime_predict_history = $time;
			stats1.errors_predict_history = stats1.errors_predict_history+1'b1; end

	end
endmodule

detail_description:
Build a gshare branch predictor with 7-bit pc and 7-bit global history, hashed (using xor) into a 7-bit index. This index accesses a 128-entry table of two-bit saturating counters. The branch predictor should contain a 7-bit global branch history register. The branch predictor has two sets of interfaces: One for doing predictions and one for doing training. The prediction interface is used in the processor's Fetch stage to ask the branch predictor for branch direction predictions for the instructions being fetched. Once these branches proceed down the pipeline and are executed, the true outcomes of the branches become known. The branch predictor is then trained using the actual branch direction outcomes.
// When a branch prediction is requested (predict_valid = 1) for a given pc, the branch predictor produces the predicted branch direction and state of the branch history register used to make the prediction. The branch history register is then updated (at the next positive clock edge) for the predicted branch.
// When training for a branch is requested (train_valid = 1), the branch predictor is told the pc and branch history register value for the branch that is being trained, as well as the actual branch outcome and whether the branch was a misprediction (needing a pipeline flush). Update the pattern history table (PHT) to train the branch predictor to predict this branch more accurately next time. In addition, if the branch being trained is mispredicted, also recover the branch history register to the state immediately after the mispredicting branch completes execution.
// If training for a misprediction and a prediction (for a different, younger instruction) occurs in the same cycle, both operations will want to modify the branch history register. When this happens, training takes precedence, because the branch being predicted will be discarded anyway. If training and prediction of the same PHT entry happen at the same time, the prediction sees the PHT state before training because training only modifies the PHT at the next positive clock edge. The following timing diagram shows the timing when training and predicting PHT entry 0 at the same time. The training request at cycle 4 changes the PHT entry state in cycle 5, but the prediction request in cycle 4 outputs the PHT state at cycle 4, without considering the effect of the training request in cycle 4. Reset is asynchronous active-high.


prompt:
module top_module (
	input a,
	input b,
	input c,
	input d,
	input e,
	output [24:0] out
);

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

	assign out = ~{ {5{a}}, {5{b}}, {5{c}}, {5{d}}, {5{e}} } ^ {5{a,b,c,d,e}};

endmodule

module stimulus_gen (
	input clk,
	output logic a, b, c, d, e
);

	initial begin
		repeat(100) @(posedge clk, negedge clk)
			{a,b,c,d,e} <= $random;
		$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 e;
	logic [24:0] out_ref;
	logic [24:0] out_dut;

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

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

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

	top_module top_module1 (
		.a,
		.b,
		.c,
		.d,
		.e,
		.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: Given five 1-bit signals (a, b, c, d, and e), compute all 25 pairwise one-bit comparisons in the 25-bit output vector. The output should be 1 if the two bits being compared are equal. Example: out[24] = ~a ^ a; out[23] = ~a ^ b; out[22] = ~a ^ c; ... out[ 1] = ~e ^ d; out[ 0] = ~e ^ e.


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

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

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) & x;

endmodule

module stimulus_gen (
	input clk,
	output logic x,
	output logic y
);

	always @(posedge clk, negedge clk)
		{x, y} <= $random % 4;

	initial begin
		repeat(101) @(negedge clk);
		#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

detail_description: Implement the boolean function z = (x^y) & x.


prompt:
module top_module(
	input clk,
	input [7:0] d,
	input reset,
	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,
	input reset,
	output reg [7:0] q);

	always @(negedge clk)
		if (reset)
			q <= 8'h34;
		else
			q <= d;

endmodule

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

// 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

	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

	initial begin
		reset <= 1;
		d <= $random;
		@(negedge clk);
		@(negedge clk);
		wavedrom_start("Synchronous active-high reset");
		reset_test();
		repeat(10) @(negedge clk)
			d <= $random;
		wavedrom_stop();

		repeat(400) @(posedge clk, negedge clk) begin
			reset <= !($random & 15);
			d <= $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 [7:0] d;
	logic reset;
	logic [7:0] q_ref;
	logic [7:0] q_dut;

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

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

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

	top_module top_module1 (
		.clk,
		.d,
		.reset,
		.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 with active high synchronous reset. The flip-flops must be reset to 0x34 rather than zero. All DFFs should be triggered by the negative edge of clk.


task_id: notgate

prompt:
module top_module(
	input in,
	output out
);

canonical_solution:
	assign out = ~in;

endmodule

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

	assign out = ~in;

endmodule

module stimulus_gen (
	input clk,
	output reg 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
		in <= 1'b0;
		wavedrom_start("Inversion");
		repeat(20) @(posedge clk)
			in <= $random;
		wavedrom_stop();

		repeat(200) @(posedge clk, negedge clk)
			in <= $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 in;
	logic out_ref;
	logic out_dut;

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

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

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

	top_module top_module1 (
		.in,
		.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 a NOT gate.


prompt:
module top_module (
	input a,
	input b,
	input c,
	output w,
	output x,
	output y,
	output z  );

canonical_solution:
	assign {w,x,y,z} = {a,b,b,c};

endmodule

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

	assign {w,x,y,z} = {a,b,b,c};

endmodule

module stimulus_gen (
	input clk,
	output logic a, b, c,
	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)
		{a,b,c} <= $random;

	initial begin
		@(negedge clk) wavedrom_start();
			repeat(8) @(posedge clk);
		@(negedge clk) wavedrom_stop();
		repeat(100) @(negedge clk);
		$finish;
	end

endmodule

module tb();

	typedef struct packed {
		int errors;
		int errortime;
		int errors_w;
		int errortime_w;
		int errors_x;
		int errortime_x;
		int errors_y;
		int errortime_y;
		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 a;
	logic b;
	logic c;
	logic w_ref;
	logic w_dut;
	logic x_ref;
	logic x_dut;
	logic y_ref;
	logic y_dut;
	logic z_ref;
	logic z_dut;

	initial begin
		$dumpfile("wave.vcd");
		$dumpvars(1, stim1.clk, tb_mismatch ,a,b,c,w_ref,w_dut,x_ref,x_dut,y_ref,y_dut,z_ref,z_dut );
	end

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

	stimulus_gen stim1 (
		.clk,
		.* ,
		.a,
		.b,
		.c );
	reference_module good1 (
		.a,
		.b,
		.c,
		.w(w_ref),
		.x(x_ref),
		.y(y_ref),
		.z(z_ref) );

	top_module top_module1 (
		.a,
		.b,
		.c,
		.w(w_dut),
		.x(x_dut),
		.y(y_dut),
		.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_w) $display("Hint: Output '%s' has %0d mismatches. First mismatch occurred at time %0d.", "w", stats1.errors_w, stats1.errortime_w);
		else $display("Hint: Output '%s' has no mismatches.", "w");
		if (stats1.errors_x) $display("Hint: Output '%s' has %0d mismatches. First mismatch occurred at time %0d.", "x", stats1.errors_x, stats1.errortime_x);
		else $display("Hint: Output '%s' has no mismatches.", "x");
		if (stats1.errors_y) $display("Hint: Output '%s' has %0d mismatches. First mismatch occurred at time %0d.", "y", stats1.errors_y, stats1.errortime_y);
		else $display("Hint: Output '%s' has no mismatches.", "y");
		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 = ( { w_ref, x_ref, y_ref, z_ref } === ( { w_ref, x_ref, y_ref, z_ref } ^ { w_dut, x_dut, y_dut, z_dut } ^ { w_ref, x_ref, y_ref, 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 (w_ref !== ( w_ref ^ w_dut ^ w_ref ))
		begin if (stats1.errors_w == 0) stats1.errortime_w = $time;
			stats1.errors_w = stats1.errors_w+1'b1; end
		if (x_ref !== ( x_ref ^ x_dut ^ x_ref ))
		begin if (stats1.errors_x == 0) stats1.errortime_x = $time;
			stats1.errors_x = stats1.errors_x+1'b1; end
		if (y_ref !== ( y_ref ^ y_dut ^ y_ref ))
		begin if (stats1.errors_y == 0) stats1.errortime_y = $time;
			stats1.errors_y = stats1.errors_y+1'b1; 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:
Create a module with 3 inputs and 4 outputs that behaves like wires that makes these connections: a -> w
// ; b -> x; b -> y; c -> z.