def run_general(self): last = self.time[1] m = self.module core: Core = self.uut comb = m.d.comb lhs = Signal(unsigned(core.xlen)) rhs = Signal(unsigned(core.xlen)) bgeu_res = Signal(name="bgeu_res") comb += lhs.eq(last.r[last.btype.rs1]) comb += rhs.eq(last.r[last.btype.rs2]) comb += bgeu_res.eq(lhs >= rhs) with m.If(bgeu_res): self.assert_jump_was_taken() with m.Else(): self.assert_no_jump_taken() lhs_bz = Signal() # bz = below-zero in signed representation rhs_bz = Signal() comb += lhs_bz.eq(lhs[core.xlen - 1]) comb += rhs_bz.eq(rhs[core.xlen - 1]) with m.If(lhs_bz & (~rhs_bz)): self.assert_jump_was_taken() with m.Elif((~lhs_bz) & (rhs_bz)): self.assert_no_jump_taken()
def run_general(self): last = self.time[1] m = self.module core: Core = self.uut comb = m.d.comb bltu_lhs = Signal(unsigned(core.xlen)) bltu_rhs = Signal(unsigned(core.xlen)) bltu_res = Signal(name="bltu_res") comb += bltu_lhs.eq(last.r[last.btype.rs1]) comb += bltu_rhs.eq(last.r[last.btype.rs2]) comb += bltu_res.eq(bltu_lhs < bltu_rhs) with m.If(bltu_res): self.assert_jump_was_taken() with m.Else(): self.assert_no_jump_taken() bltu_lhs_bz = Signal() # bz = below-zero in signed variant bltu_rhs_bz = Signal() comb += bltu_lhs_bz.eq(bltu_lhs[core.xlen - 1]) comb += bltu_rhs_bz.eq(bltu_rhs[core.xlen - 1]) with m.If(bltu_lhs_bz & (~bltu_rhs_bz)): self.assert_no_jump_taken() with m.Elif((~bltu_lhs_bz) & (bltu_rhs_bz)): self.assert_jump_was_taken()
def comparison_impl(self, rv1, rv2): core : Core = self.core m = core.current_module comb = m.d.comb rv1_unsigned = Signal(unsigned(core.xlen)) rv2_unsigned = Signal(unsigned(core.xlen)) comb += rv1_unsigned.eq(rv1) comb += rv2_unsigned.eq(rv2) return rv1_unsigned < rv2_unsigned
def __init__(self, ParityCheckMatrix, codeword_width): #[PARAMETER] - codeword_width: Width of the output Codeword self.codeword_width = int(codeword_width) #[PARAMETER] - data_output_matrix_rows: Rows of the Generator Matrix self.data_output_matrix_rows = int(len(ParityCheckMatrix)) #[CONSTANT] - parity_check_matrix: A parity check matrix constant self.parity_check_matrix = Array([ Const(ParityCheckMatrix[_][0], unsigned(self.codeword_width)) for _ in range(self.data_output_matrix_rows) ]) #[INPUT] - start: The start signal to start the decoding process(codeword) self.start = Signal(1) #[INPUT] - data_input: The data to be encoded self.data_input = Signal(codeword_width) #[OUTPUT] - data_output: The result of each row parity check self.data_output = Signal(self.data_output_matrix_rows, reset=0) #[OUTPUT] - done: The done signal to indicate that the decoding process has stopped. self.done = Signal(1, reset=0)
def __init__(self, GeneratorMatrix, codeword_width): #[PARAMETER] - codeword_width: Width of the output Codeword self.codeword_width = int(codeword_width) #[PARAMETER] - data_input_length: Width of the data input self.data_input_length = int(len(GeneratorMatrix)) #[CONSTANT] - gen_matrix: A generator matrix constant self.gen_matrix = Array([ Const(GeneratorMatrix[_][0], unsigned(self.codeword_width)) for _ in range(self.data_input_length) ]) #[INPUT] - start: The start signal to start the encoding process(codeword) self.start = Signal(1) #[INPUT] - data_input: The data to be encoded self.data_input = Signal(self.data_input_length) #[OUTPUT] - data_output: The encoded data (codeword) self.data_output = Signal(self.codeword_width, reset=0) #[OUTPUT] - done: The done signal to indicate that encoding has completed. self.done = Signal(1, reset=0)
def __init__(self, name: str = None): super().__init__( Layout([ ("address", unsigned(16)), ("data_in", unsigned(8)), ("data_out", unsigned(8)), ("rw", unsigned(1)), ("vma", unsigned(1)), ("ba", unsigned(1)), ("nmi", unsigned(1)), ("irq", unsigned(1)), ]), name=name, )
def selftest(): ps0 = PipeSpec(8) assert ps0.data_width == 8 assert ps0.flags == 0 assert type(ps0.dsol) is Shape assert ps0.dsol == unsigned(8) assert ps0.start_stop is False assert ps0.data_size is False assert ps0.as_int == 8 pi0 = ps0.inlet() assert isinstance(pi0, PipeInlet) assert isinstance(pi0, Record) assert isinstance(pi0, Value) assert pi0.o_data.shape() == unsigned(8) c0 = pi0.flow_to(ps0.outlet()) assert len(c0) == 3 assert repr(c0[0]) == '(eq (sig i_data) (sig pi0__o_data))' assert repr(c0[1]) == '(eq (sig i_valid) (sig pi0__o_valid))' assert repr(c0[2]) == '(eq (sig pi0__i_ready) (sig o_ready))' ps1 = PipeSpec(signed(5), flags=DATA_SIZE) assert ps1.data_width == 5 assert ps1.flags == DATA_SIZE assert type(ps1.dsol) is Shape assert ps1.dsol == signed(5) assert ps1.start_stop is False assert ps1.data_size is True assert ps1.as_int == 256 + 5 pi1 = ps1.inlet() assert isinstance(pi1, PipeInlet) assert isinstance(pi1, Record) assert isinstance(pi1, Value) assert pi1.o_data.shape() == signed(5) c1 = ps1.outlet().flow_from(pi1) assert len(c1) == 4 ps2 = PipeSpec((('a', signed(4)), ('b', unsigned(2))), flags=START_STOP) assert ps2.data_width == 6 assert ps2.flags == START_STOP assert type(ps2.dsol) is Layout assert ps2.dsol == Layout((('a', signed(4)), ('b', unsigned(2)))) assert ps2.start_stop is True assert ps2.data_size is False assert ps2.as_int == 512 + 6 pi2 = ps2.inlet() assert isinstance(pi2, PipeInlet) assert isinstance(pi2, Record) assert isinstance(pi2, Value) assert pi2.o_data.shape() == unsigned(4 + 2) po2 = ps2.outlet() assert isinstance(po2, PipeOutlet) assert po2.i_data.shape() == unsigned(4 + 2) c2 = pi2.flow_to(po2) assert len(c2) == 5 ps3 = PipeSpec.from_int(START_STOP | DATA_SIZE | 10) assert ps3.data_width == 10 assert ps3.flags == START_STOP | DATA_SIZE assert type(ps3.dsol) is Shape assert ps3.dsol == unsigned(10) assert ps3.start_stop is True assert ps3.data_size is True assert ps3.as_int == 512 + 256 + 10 pi3 = ps3.inlet(name='inlet_3') assert isinstance(pi3, PipeInlet) assert isinstance(pi3, Record) assert isinstance(pi3, Value) assert pi3.o_data.shape() == unsigned(10) inlet_3 = ps3.inlet() po3 = ps3.outlet(name='outlet_3') outlet_3 = ps3.outlet() assert repr(pi3) == repr(inlet_3) assert repr(po3) == repr(outlet_3) assert repr(pi3.fields) == repr(inlet_3.fields) assert repr(po3.fields) == repr(outlet_3.fields) c3 = pi3.flow_to(po3) c3a = outlet_3.flow_from(inlet_3) assert len(c3) == 6 assert len(c3a) == 6
def __init__(self): self.x = Signal(8) self.y = Signal(8) self.out = Signal(unsigned(8))
def elaborate(self, platform): phase = Signal(self.phase_depth) note = Signal.like(self.note_in.i_data.note) mod = Signal.like(self.mod_in) pw = Signal.like(self.pw_in) octave = Signal(range(OCTAVES)) step = Signal(range(STEPS)) base_inc = Signal(self.inc_depth) step_incs = Array( [Signal.like(base_inc, reset=inc) for inc in self._base_incs]) inc = Signal.like(phase) pulse_sample = Signal.like(self.pulse_out.o_data) saw_sample = Signal.like(self.saw_out.o_data) m = Module() with m.If(self.sync_in): m.d.sync += [ phase.eq(0), # self.rdy_out.eq(False), ] m.d.comb += [ self.note_in.o_ready.eq(True), ] with m.If(self.note_in.received()): m.d.sync += [ note.eq(self.note_in.i_data.note), octave.eq(div12(self.note_in.i_data.note)), ] # Calculate pulse wave edges. The pulse must rise and fall # exactly once per cycle. prev_msb = Signal() new_cycle = Signal() pulse_up = Signal() up_latch = Signal() pw8 = Cat(pw, Const(0, unsigned(1))) m.d.sync += [ prev_msb.eq(phase[-1]), ] m.d.comb += [ new_cycle.eq(~phase[-1] & prev_msb), # Widen pulse to one sample period minimum. pulse_up.eq(new_cycle | (up_latch & (phase[-8:] <= pw8))), ] m.d.sync += [ up_latch.eq((new_cycle | up_latch) & pulse_up), ] with m.FSM(): with m.State(FSM.START): m.d.sync += [ # note.eq(self.note_in), mod.eq(self.mod_in), pw.eq(self.pw_in), # octave.eq(div12(self.note_in)), ] m.next = FSM.MODULUS with m.State(FSM.MODULUS): m.d.sync += [ step.eq(note - mul12(octave)), ] m.next = FSM.LOOKUP with m.State(FSM.LOOKUP): m.d.sync += [ base_inc.eq(step_incs[step]), ] # m.next = FSM.MODULATE m.next = FSM.SHIFT # with m.State(FSM.MODULATE): # ... # m.next = FSM.SHIFT with m.State(FSM.SHIFT): m.d.sync += [ inc.eq((base_inc << octave)[-self.shift:]), ] m.next = FSM.ADD with m.State(FSM.ADD): m.d.sync += [ phase.eq(phase + inc), ] m.next = FSM.SAMPLE with m.State(FSM.SAMPLE): samp_depth = self.saw_out.o_data.shape()[0] samp_max = 2**(samp_depth - 1) - 1 m.d.sync += [ pulse_sample.eq(Mux(pulse_up, samp_max, -samp_max)), saw_sample.eq(samp_max - phase[-samp_depth:]), ] m.next = FSM.EMIT with m.State(FSM.EMIT): with m.If(self.saw_out.i_ready & self.pulse_out.i_ready): m.d.sync += [ self.pulse_out.o_valid.eq(True), self.pulse_out.o_data.eq(pulse_sample), self.saw_out.o_valid.eq(True), self.saw_out.o_data.eq(saw_sample), ] m.next = FSM.START with m.If(self.pulse_out.sent()): m.d.sync += [ self.pulse_out.o_valid.eq(False), ] with m.If(self.saw_out.sent()): m.d.sync += [ self.saw_out.o_valid.eq(False), ] return m
def elaborate(self, platform): #Instantiate the Module m = Module() #[ARRAY[SIGNAL]] - stage_1_working_matrix - An array of signals which represents the parity matrix used to validate the input codeword stage_1_working_matrix = Array([ Signal(unsigned(self.codeword_width), reset=0) for _ in range(self.data_output_matrix_rows) ]) #[ARRAY[SIGNAL]] - stage_2_adder_buffer - An array of signals which are used to calculate whether there are an even number of 1s in each parity check row stage_2_adder_buffer = Array([ Signal(unsigned(self.codeword_width), reset=0, name="stage_2_adder_buffer") for _ in range(self.data_output_matrix_rows) ]) #[SIGNAL] - stage_2_counter - Counts the worst case scenario for the even 1s calculation stage_2_counter = Signal(self.codeword_width) #[SIGNAL] - pipeline_stage - Signal to indicate whether we are in pipeline stage 0 or 1 pipeline_stage = Signal(1) #[SIGNAL] - running - Signal to indicate that we are currently running running = Signal(1, reset=0) #if start bit is asserted, reset the system with m.If(self.start): for i in range(0, self.data_output_matrix_rows): m.d.sync += [ running.eq(1), stage_1_working_matrix[i].eq(0), stage_2_adder_buffer[i].eq(0), stage_2_counter.eq(0), self.done.eq(0), self.data_output.eq(0b000), pipeline_stage.eq(0), ] #First Pipeline Stage (0) #Data_input ANDed with each row of the parity check matrix with m.If(running & (pipeline_stage == 0)): for i in range(0, self.data_output_matrix_rows): m.d.sync += [ stage_1_working_matrix[i].eq(self.data_input & self.parity_check_matrix[i]) ] m.d.sync += [pipeline_stage.eq(1)] #Second Pipeline Stage (1) #Accumulate the ANDed data to calculate if there are an even number of 1s. with m.If(running & (pipeline_stage == 1)): m.d.sync += [stage_2_counter.eq(stage_2_counter + 1)] for i in range(0, self.data_output_matrix_rows): for n in range(1, self.codeword_width): if (n == 1): m.d.sync += [ stage_2_adder_buffer[i] [n].eq(stage_1_working_matrix[i][n] ^ stage_1_working_matrix[i][n - 1]) ] else: m.d.sync += [ stage_2_adder_buffer[i] [n].eq(stage_2_adder_buffer[i][n - 1] ^ stage_1_working_matrix[i][n]) ] #Output the result of each parity check row comparison (1=Fail, 0=Pass) with m.If(stage_2_counter == (self.codeword_width)): for i in range(0, self.data_output_matrix_rows): m.d.sync += [ self.data_output[(self.data_output_matrix_rows - 1) - i].eq(stage_2_adder_buffer[i][ self.codeword_width - 1]), running.eq(0), self.done.eq(1) ] return m
def elaborate(self, platform): #Instantiate the Module m = Module() #[ARRAY[SIGNAL]] - working_matrix - An array of signals which represents the matrix used to calculate the output codeword. working_matrix = Array([ Signal(unsigned(self.codeword_width), reset=0) for _ in range(self.data_input_length) ]) #[ARRAY[SIGNAL]] - adder_buffer - An array of signals which is used to accumulate the columns of the working matrix to calculate the codeword adder_buffer = Array([ Signal(unsigned(self.data_input_length), reset=0) for _ in range(self.codeword_width) ]) #[SIGNAL] - cnt - A signal to count the steps completed in the encoding process cnt = Signal(self.data_input_length) #[SIGNAL] - running - A signal which is used to indicate the pipeline is running. running = Signal(1, reset=0) #[SIGNAL] - accumulation_completed - A signal which is used to indicate when the accumulation process has completed. accumulation_completed = Signal(1) #[SIGNAL] - data_input_copy - Internal copy of the data_input data_input_copy = Signal(self.data_input_length) #The accumulation process completes in fixed time complexity in (n-1) clock cycles, where n is the length of the data input m.d.comb += accumulation_completed.eq(cnt == self.data_input_length - 1) #If 'start' is asserted, reset the adder_buffer, cnt, done and output variables. with m.If(self.start): for i in range(0, self.codeword_width): m.d.sync += [adder_buffer[i].eq(0)] m.d.sync += [ cnt.eq(0), self.done.eq(0), self.data_output.eq(0), data_input_copy.eq(self.data_input), running.eq(1) ] #If 'accumulation_completed' is not satisfied, increment cnt with m.Elif(~accumulation_completed & running): m.d.sync += [cnt.eq(cnt + 1)] #Complete the first stage of the accumulation - AND the input data with the genmatrix #Since this is in the combinatorial domain, there is 'no penalty' as the size of the generator matrix and data input increases for i in range(0, self.codeword_width): for n in range(0, self.data_input_length): m.d.comb += [ working_matrix[n][i]. eq(self.gen_matrix[n][i] & data_input_copy[(self.data_input_length - n) - 1]) ] #Accumulate the columns of the matrix, with the Gallagher Modulo 2 rules #https://ieeexplore.ieee.org/document/1057683 for i in range(0, self.codeword_width): for n in range(1, self.data_input_length): if (n == 1): m.d.sync += [ adder_buffer[i][n].eq(working_matrix[n][i] ^ working_matrix[n - 1][i]) ] else: m.d.sync += [ adder_buffer[i][n].eq(adder_buffer[i][n - 1] ^ working_matrix[n][i]) ] #Present the result on the output register and set the 'done' flag. with m.Elif(accumulation_completed & running): for i in range(0, self.codeword_width): m.d.sync += [ self.data_output[i].eq( adder_buffer[i][self.data_input_length - 1]), self.done.eq(1), running.eq(0) ] return m
#!/usr/bin/env nmigen from nmigen import Const, Elaboratable, Module, Signal, unsigned from nmigen_lib.pipe import PipeSpec from nmigen_lib.util.main import Main from nmigen_lib.util import delay from synth.midi import note_msg_spec voice_note_spec = PipeSpec(( ('note', unsigned(7)), )) voice_gate_spec = PipeSpec(( ('gate', unsigned(1)), ('velocity', unsigned(7)), )) class MonoPriority(Elaboratable): """Choose highest priority notes for monophonic synth. Channel = None means merge all MIDI channels. use_velocity: if false, output velocity is constant at 64. """ def __init__(self, channel=None, use_velocity=False): self.channel = channel
def elaborate(self, platform): #Instantiate the Module m = Module() #Instantiate a decoder/validator for each bit-flip combination of the input codeword for i in range(0, self.codeword_width + 1): m.submodules["decoder" + str(i)] = LDPC_Decoder_Validator( self.ParityCheckMatrixPythonArray, self.codeword_width) #codeword_list - An array containing the input codeword and copies of the input codeword, each with a different bit flipped codeword_list = Array([ Signal(unsigned(self.codeword_width), reset=0) for _ in range(self.codeword_width + 1) ]) #decoder_output_list - An array containing the parity check status of each parity check row for an input codeword decoder_output_list = Array([ Signal(unsigned(self.ParityCheckMatrixRows), reset=0) for _ in range(self.codeword_width + 1) ]) #decoders_done - A signal which lets the top level know when the submodules have finished decoding/validating decoders_done = Signal(1) m.d.comb += decoders_done.eq( m.submodules["decoder" + str(self.codeword_width)].done) #counter - A timeout counter for catching when the decoder never finishes decoding counter = Signal(self.codeword_width) #pipeline_stage - A signal for keeping track of the pipeline stage pipeline_stage = Signal(3, reset=0) #pipeline_stage - A signal for starting the submodules start_submodules = Signal(1, reset=0) for i in range(0, self.codeword_width + 1): m.d.comb += m.submodules["decoder" + str(i)].start.eq(start_submodules) m.d.sync += m.submodules["decoder" + str(i)].data_input.eq( codeword_list[i]) m.d.comb += decoder_output_list[i].eq( m.submodules["decoder" + str(i)].data_output) #Reset the relevant registers/wires and load the input codeword into a decoder input register with m.If(self.start): m.d.sync += [ codeword_list[self.codeword_width].eq(self.data_input), self.data_output.eq(0), self.done.eq(0), self.success.eq(0), counter.eq(0), pipeline_stage.eq(1) ] #Load the input codeword into the codeword list with m.Elif(pipeline_stage == 1): for i in range(0, self.codeword_width): m.d.sync += [ codeword_list[i].eq(codeword_list[self.codeword_width]), pipeline_stage.eq(pipeline_stage + 1) ] #Flip the relevant bit on the codewords in the codeword list with m.Elif(pipeline_stage == 2): for i in range(0, self.codeword_width): m.d.sync += [ codeword_list[i][i].eq(~codeword_list[i][i]), pipeline_stage.eq(pipeline_stage + 1) ] #Start validating all the codeword variations (Set Start Bit to 1) with m.Elif(pipeline_stage == 3): for i in range(0, self.codeword_width): m.d.sync += [ start_submodules.eq(1), pipeline_stage.eq(pipeline_stage + 1) ] #Start validating all the codeword variations (Set Start Bit to 0) with m.Elif(pipeline_stage == 4): for i in range(0, self.codeword_width): m.d.sync += [ start_submodules.eq(0), pipeline_stage.eq(pipeline_stage + 1) ] #Start counting the timeout and validating if any of the submodules was successful in validating the codeword. #Finally, output success or failure along with output data and STOP. with m.Elif(pipeline_stage == 5 & (~self.done) & (~self.start)): for i in range(0, self.codeword_width + 1): m.d.sync += counter.eq(counter + 1) with m.If((decoders_done) & (counter > (self.codeword_width + 2))): m.d.sync += [self.done.eq(1), self.success.eq(0)] with m.Elif((decoders_done)): for i in range(0, self.codeword_width + 1): with m.If(decoder_output_list[i] == 0b000): m.d.sync += [ self.data_output.eq(codeword_list[ self.codeword_width][self.codeword_width - self.data_output_width:]), self.done.eq(1), self.success.eq(1) ] return m
#!/usr/bin/env nmigen from collections import namedtuple from nmigen import Elaboratable, Module, Signal, unsigned from nmigen.asserts import Assert from nmigen.back.pysim import Passive from nmigen_lib.pipe import PipeSpec from nmigen_lib.util import Main, delay note_msg_spec = PipeSpec(( ('onoff', unsigned(1)), ('channel', unsigned(4)), ('note', unsigned(7)), ('velocity', unsigned(7)), )) class MIDIDecoder(Elaboratable): def __init__(self): self.serial_in = PipeSpec(8).outlet() self.note_msg_out = note_msg_spec.inlet() def elaborate(self, platform): def is_message_start(byte): # any byte with the high bit set return byte[7] != 0