def test_dct_1d(): """1D-DCT MyHDL Test In this test is verified the correct behavior of the 1d-dct module """ samples, fract_bits, out_prec, N = 10, 14, 10, 9 clock = Signal(bool(0)) reset = ResetSignal(1, active=True, async=True) inputs = input_1d_1st_stage() outputs = output_interface(out_prec, N) in_out_data = InputsAndOutputs(samples, N) in_out_data.initialize() @myhdl.block def bench_dct_1d(): tdut = dct_1d(inputs, outputs, clock, reset, fract_bits, out_prec, N) tbclk = clock_driver(clock) @instance def tbstim(): yield pulse_reset(reset, clock) inputs.data_valid.next = True for i in range(samples): for j in range(N): inputs.data_in.next = in_out_data.inputs[i][j] yield clock.posedge @instance def monitor(): outputs_count = 0 while(outputs_count != samples): yield clock.posedge yield delay(1) if outputs.data_valid: # convert flat signal to array of signals out_print(in_out_data.outputs[outputs_count], outputs.out_sigs) outputs_count += 1 raise StopSimulation return tdut, tbclk, tbstim, monitor run_testbench(bench_dct_1d)
def dct_2d(inputs, outputs, clock, reset, num_fractional_bits=14, stage_1_prec=10, out_prec=10, N=8): """2D-DCT Module This module performs the 2D-DCT Transformation. It takes serially the inputs of a NxN block and outputs parallely the transformed block in 64 signals. The row-column decomposition method used to implement the 2d-dct. The parameter num_fractional_bits is used to define the fractional bits for the fixed point representation of the coefficients. The stage_1_prec parameter defines the fractional bits for the fixed point representation of the 1st stage 1d-dct outputs. The out_prec defines the fractional bits for the ouputs of the 2d-dct and the N parameter defines the size of the NxN block. Inputs: data_in, data_valid, clock, reset Outputs: NxN signals in the list out_sigs, data_valid Parameters: num_fractional_bits, stage_1_prec, out_prec, N """ first_1d_output = output_interface(stage_1_prec, N) input_1d_stage_1 = input_1d_1st_stage() first_1d = dct_1d(input_1d_stage_1, first_1d_output, clock, reset, num_fractional_bits, stage_1_prec, N) data_in_signed = Signal(intbv(0, min=-input_1d_stage_1.in_range, max=input_1d_stage_1.in_range)) data_valid_reg = Signal(bool(0)) data_valid_reg2 = Signal(bool(0)) counter = Signal(intbv(0, min=0, max=N)) outputs_data_valid = Signal(bool(0)) # list of interfaces for the 2nd stage 1d-dct modules inputs_2nd_stage = [] outputs_2nd_stage = [] for i in range(N): inputs_2nd_stage += [input_1d_1st_stage(first_1d_output.out_precision)] outputs_2nd_stage += [output_interface(out_prec, N)] stage_2_insts = [] for i in range(N): stage_2_insts += [dct_1d(inputs_2nd_stage[i], outputs_2nd_stage[i], clock, reset, num_fractional_bits, stage_1_prec, N)] stage_2_insts += [assign(inputs_2nd_stage[i].data_in, first_1d_output.out_sigs[i])] stage_2_insts += [assign(inputs_2nd_stage[i].data_valid, first_1d_output.data_valid)] for j in range(N): stage_2_insts += [assign(outputs.out_sigs[j * N + i], outputs_2nd_stage[i].out_sigs[j])] stage_2_insts += [assign(outputs_data_valid, outputs_2nd_stage[0].data_valid)] @always_seq(clock.posedge, reset=reset) def input_subtract(): """Align to zero each input""" if inputs.data_valid: data_in_signed.next = inputs.data_in input_1d_stage_1.data_in.next = data_in_signed - 128 data_valid_reg.next = inputs.data_valid input_1d_stage_1.data_valid.next = data_valid_reg @always_comb def second_stage_output(): outputs.data_valid.next = data_valid_reg2 @always_seq(clock.posedge, reset=reset) def counter_update(): """Counter update""" if outputs_data_valid: if counter == N - 1: counter.next = 0 else: counter.next = counter + 1 @always_comb def data_valid_2d(): """Data valid signal assignment when the outputs are valid""" if outputs_data_valid and counter == 0: data_valid_reg2.next = True else: data_valid_reg2.next = False return (stage_2_insts, input_subtract, second_stage_output, counter_update, data_valid_2d, first_1d)
def dct_2d(inputs, outputs, clock, reset, num_fractional_bits=14, stage_1_prec=10, out_prec=10, N=8): """2D-DCT Module This module performs the 2D-DCT Transformation. It takes serially the inputs of a NxN block and outputs parallely the transformed block in 64 signals. Inputs: data_in, data_valid Outputs: NxN signals in the list out_sigs, data_valid """ first_1d_output = output_interface(stage_1_prec, N) input_1d_stage_1 = input_1d_1st_stage() first_1d = dct_1d(input_1d_stage_1, first_1d_output, clock, reset, num_fractional_bits, stage_1_prec, N) data_in_signed = Signal(intbv(0, min=-input_1d_stage_1.in_range, max=input_1d_stage_1.in_range)) data_valid_reg = Signal(bool(0)) data_valid_reg2 = Signal(bool(0)) counter = Signal(intbv(0, min=0, max=N)) outputs_data_valid = Signal(bool(0)) # list of interfaces for the 2nd stage 1d-dct modules inputs_2nd_stage = [] outputs_2nd_stage = [] for i in range(N): inputs_2nd_stage += [input_1d_2nd_stage(first_1d_output.out_precision)] outputs_2nd_stage += [output_interface(out_prec, N)] """the blocks below are used for the list of signal elaboration""" @block def assign(data_in, data_valid, data_in_temp, data_valid_temp): """used to assign the signals data_in and data_valid of the first 1d-dct module to the second stage 1d-dct modules""" @always_comb def assign(): data_in.next = data_in_temp data_valid.next = data_valid_temp return assign @block def assign_2(outputs, outputs_2nd_stage, io): """used to assigns the output signals of the 2nd stage 1d-dct modules to the outputs signals of the top level 2d-dct""" @block def assign(y, x): @always_comb def assign(): y.next = x return assign g = [None for _ in range(N)] for i in range(N): g[i] = assign(outputs.out_sigs[i*N + io], outputs_2nd_stage.out_sigs[i]) return g @block def assign_3(y, x): """used to make a simple assignment of the data_valid signals of the 2nd stage 1d-dct modules to a temp signal which used in the 2d-dct module""" @always_comb def assign(): y.next = x return assign stage_2_insts = [] for i in range(N): stage_2_insts += [dct_1d(inputs_2nd_stage[i], outputs_2nd_stage[i], clock, reset, num_fractional_bits, stage_1_prec, N)] stage_2_insts += [assign(inputs_2nd_stage[i].data_in, inputs_2nd_stage[i].data_valid, first_1d_output.out_sigs[i], first_1d_output.data_valid)] stage_2_insts += [assign_2(outputs, outputs_2nd_stage[i], i)] stage_2_insts += [assign_3(outputs_data_valid, outputs_2nd_stage[0].data_valid)] @always_seq(clock.posedge, reset=reset) def input_subtract(): """Align to zero each input""" if inputs.data_valid: data_in_signed.next = inputs.data_in input_1d_stage_1.data_in.next = data_in_signed - 128 data_valid_reg.next = inputs.data_valid input_1d_stage_1.data_valid.next = data_valid_reg @always_comb def second_stage_output(): outputs.data_valid.next = data_valid_reg2 @always_seq(clock.posedge, reset=reset) def counter_update(): """Counter update""" if outputs_data_valid: if counter == N - 1: counter.next = 0 else: counter.next = counter + 1 @always_comb def data_valid_2d(): """Data valid signal assignment when the outputs are valid""" if outputs_data_valid and counter == 0: data_valid_reg2.next = True else: data_valid_reg2.next = False return (stage_2_insts, input_subtract, second_stage_output, counter_update, data_valid_2d, first_1d)
def test_dct_1d_conversion(): """Convertible 1D-DCT Test This is the convertible testbench which ensures that the overall design is convertible and verified for its correct behavior""" samples, fract_bits, out_prec, N = 10, 14, 10, 8 clock = Signal(bool(0)) reset = ResetSignal(1, active=True, async=True) inputs = input_1d_1st_stage() outputs = output_interface(out_prec, N) in_out_data = InputsAndOutputs(samples, N) in_out_data.initialize() inputs_rom, expected_outputs_rom = in_out_data.get_rom_tables() @myhdl.block def bench_dct_1d(): print_sig = [Signal(intbv(0, min=-2**out_prec, max=2**out_prec)) for _ in range(N)] print_sig_1 = [Signal(intbv(0, min=-2**out_prec, max=2**out_prec)) for _ in range(N)] tdut = dct_1d(inputs, outputs, clock, reset, fract_bits, out_prec, N) tbclk = clock_driver(clock) tbrst = reset_on_start(reset, clock) @instance def tbstim(): yield reset.negedge inputs.data_valid.next =True for i in range(samples * N): inputs.data_in.next = inputs_rom[i] yield clock.posedge print_assign = assign_array(print_sig_1, outputs.out_sigs) @instance def monitor(): outputs_count = 0 while outputs_count != samples: yield clock.posedge yield delay(1) if outputs.data_valid: for i in range(N): print_sig[i].next = expected_outputs_rom[outputs_count * 8 + i] yield delay(1) print("Expected Outputs") for i in range(N): print("%d" % print_sig[i]) print("Actual Outputs") for i in range(N): print("%d" % print_sig_1[i]) print("------------------------") outputs_count += 1 raise StopSimulation return tdut, tbclk, tbstim, monitor, tbrst, print_assign assert bench_dct_1d().verify_convert() == 0
def test_dct_1d_conversion(): samples, fract_bits, out_prec, N = 10, 14, 10, 8 clock = Signal(bool(0)) reset = ResetSignal(1, active=True, async=True) inputs = input_1d_1st_stage() outputs = output_interface(out_prec, N) in_out_data = InputsAndOutputs(samples, N) in_out_data.initialize() inputs_rom, expected_outputs_rom = in_out_data.get_rom_tables() @myhdl.block def bench_dct_1d(): print_sig = [Signal(intbv(0, min=-2**out_prec, max=2**out_prec)) for _ in range(N)] print_sig_1 = [Signal(intbv(0, min=-2**out_prec, max=2**out_prec)) for _ in range(N)] tdut = dct_1d(inputs, outputs, clock, reset, fract_bits, out_prec, N) tbclk = clock_driver(clock) tbrst = reset_on_start(reset, clock) @instance def tbstim(): yield reset.negedge inputs.data_valid.next =True for i in range(samples * N): inputs.data_in.next = inputs_rom[i] yield clock.posedge print_assign = outputs.assignment_2(print_sig_1) @instance def monitor(): outputs_count = 0 while outputs_count != samples: yield clock.posedge yield delay(1) if outputs.data_valid: for i in range(N): print_sig[i].next = expected_outputs_rom[outputs_count * 8 + i] yield delay(1) print("Expected Outputs") for i in range(N): print("%d" % print_sig[i]) print("Actual Outputs") for i in range(N): print("%d" % print_sig_1[i]) print("------------------------") outputs_count += 1 raise StopSimulation return tdut, tbclk, tbstim, monitor, tbrst, print_assign # verify and convert with GHDL verify.simulator = 'ghdl' assert bench_dct_1d().verify_convert() == 0 # verify and convert with iverilog verify.simulator = 'iverilog' assert bench_dct_1d().verify_convert() == 0