Re: [myhdl-list] Restrictions for conversion
Brought to you by:
jandecaluwe
From: Norbo <Nor...@gm...> - 2012-02-21 20:12:58
|
> I do not understand why the realVals array (list ofsignals) is used > since only one element is used at a time. yeah it deosnt realy makes sense if only one element used at a time, except for the case where you probably want to have read access to a constant mixed into another expression and then at some time later overide this data with some other value. (which would actually be like a ram access where the ram content is initialized, i have seen a post where jan wrote that he already had this code but he removed it because not every synthesis tool supported it at that time, or is there a limitation with verilog, i think vhdl should do fine now) > I believe the limitation you are trying to demonstrate is when the tuple > (ROM) access is mixed in other statements, instead of being its own > statement, i.e. rather than a separate generator to describe the ROM it > is embedded in the statements directly, e.g. > @always_comb > def hld_output(): > outData.next = inData*Table[int(dataIndex)] > For this second case to be convertible the converting code needs to do > some extra work which it does not and it is not clear if it should. The > conversion code will need to do the same conversion as the previous > (above) example, hence it will have to infer more. This has beendebated > in the past (level of inference) and there are differentopinions on the > level of inference that should be supported. Another way to do this in myhdl to avoid an "deeper level of inference" would be to use instead of the Table[] which is a tuple of ints a explicit declared signal array where the initial values of the signal array are set to the valus of the tuple, like this: signal_array=[Signal(intbv(Table[i],min=min(Table),max=max(Table)+1)) for i in range(len(Table))] an then use the signal_array in every statement where the access is mixed with other statements, e.g. @always_comb def hld_output(): outData.next = inData*signal_array[int(dataIndex)] + signal_array[int(dataIndex+1)] #.....etc This is actually working fine in myhdl simulation. The conversion to vhdl and verilog succeeds also without error or warning. but the signal_array in the vhdl code doesnt gets initialized with the Table values and outData will never get the corresponding data. So the actual workaround i am currently using is adding this code, but i think this could be a obstacle for some synthesis tools and for me it doesn't seams very neat, since it could be simply made obsolete. @always_comb def comb_logic(): for i in range(len(Table)): signal_array[int(i)].next=Table[int(i)] Ok here is the full code where i am using this workaround: (a ultra generic fir filter) ################################################################################################################ from myhdl import * def Combinatorical_adder(out,in1,in2): @always_comb def cc_logic(): out.next=in1+in2 return cc_logic ## NR_PARALLELS must be a natural divider of len(COEFFS) def Generic_FIR_filter(clk,rst,inData,inData_enable,outData,outData_valid,NR_PARALLELS,COEFFS): NR_COEFFS=len(COEFFS) coeffs_signal_array=[Signal(intbv(COEFFS[i],min=min(COEFFS),max=max(COEFFS)+1)) for i in range(NR_COEFFS)] reg_Shift_array=[Signal(intbv(0,min=inData.min,max=inData.max)) for i in range(NR_COEFFS)] reg_count=Signal(intbv(0,min=0,max=len(COEFFS))) add_conection=[Signal(intbv(0,min=outData.min,max=outData.max)) for i in range(NR_PARALLELS)] #TODO data range reg_mult_result=[Signal(intbv(0,min=outData.min,max=outData.max)) for i in range(NR_PARALLELS)] #TODO data range reg_accumulation=Signal(intbv(0,min=outData.min,max=outData.max)) reg_run_enable=Signal(bool(0)) Data_valid=Signal(bool(0)) reg_next_run_enable=Signal(bool(0)) addup_insts=[None]*NR_PARALLELS for i in range(NR_PARALLELS): if i==(NR_PARALLELS-1): addup_insts[i]=Combinatorical_adder(add_conection[i],reg_mult_result[i],0) else: addup_insts[i]=Combinatorical_adder(add_conection[i],reg_mult_result[i],add_conection[i+1]) @always(clk.posedge,rst.negedge) def seq_logic(): if rst==0: reg_count.next=0 for i in range(NR_COEFFS): reg_Shift_array[i].next=0 for i in range(NR_PARALLELS): reg_mult_result[i].next=0 reg_run_enable.next=0 Data_valid.next=0 else: outData_valid.next=Data_valid if inData_enable: #should not be enabled before data is valid reg_Shift_array[0].next=inData for i in range(NR_COEFFS-1): reg_Shift_array[int(i+1)].next=reg_Shift_array[int(i)] reg_run_enable.next=True reg_accumulation.next=0 Data_valid.next=False outData_valid.next=False if reg_run_enable: for i in range(NR_PARALLELS): reg_mult_result[int(i)].next=reg_Shift_array[int(i+reg_count)]*coeffs_signal_array[int(i+reg_count)] if reg_count==(NR_COEFFS-NR_PARALLELS): reg_count.next=0 Data_valid.next=True reg_run_enable.next=False else: reg_count.next=reg_count+NR_PARALLELS Data_valid.next=False if reg_next_run_enable: reg_accumulation.next=reg_accumulation+add_conection[0] reg_next_run_enable.next=reg_run_enable @always_comb def output_logic(): outData.next=reg_accumulation #### current workaround, ###### for i in range(NR_COEFFS): coeffs_signal_array[int(i)].next=COEFFS[int(i)] ############################################## return seq_logic,addup_insts ,output_logic #real_alu_insts,imag_alu_insts, comb_logic,seq_logic from pylab import * import scipy.signal as signal def TESTBENCH_XX(): ## Filter design COEFF_WIDTH=10 NR_COEFFS = 60 a = signal.firwin(NR_COEFFS, cutoff = 0.4, window = "hamming") filter_coefficients=tuple([int(i*2**COEFF_WIDTH) for i in a]) ## instanciation clk=Signal(bool(0)) rst=Signal(bool(0)) inData_enable=Signal(bool(0)) outData_valid=Signal(bool(0)) inData=Signal(intbv(0,min=-10,max=10)) outData=Signal(intbv(0,min=-20000,max=20000)) toVerilog(Generic_FIR_filter,clk,rst,inData,inData_enable,outData,outData_valid,NR_PARALLELS=3,COEFFS=filter_coefficients) dut_inst=Generic_FIR_filter(clk,rst,inData,inData_enable,outData,outData_valid,NR_PARALLELS=3,COEFFS=filter_coefficients) step_response=[] clock_counter=Signal(intbv(0)) @always(delay(10)) def clkgen(): clk.next = not clk clock_counter.next=clock_counter+1 @instance def stimulus(): rst.next=0 yield clk yield clk rst.next=1 yield clk yield clk #test step responce inData.next=0 inData_enable.next=1 for i in range(NR_COEFFS): yield clk.posedge inData_enable.next=0 yield clk.posedge print "wait for outData_valid" yield outData_valid step_response.append(int(outData)) yield clk.negedge inData.next=1 inData_enable.next=1 subplot(211) plot(step_response) ##step_response of HDL filter subplot(212) plot(cumsum(filter_coefficients)) ##step_response of the real filter print "Testbench Cycles:",clock_counter/2 show() raise StopSimulation return stimulus,clkgen,dut_inst sim = Simulation(TESTBENCH_XX()) sim.run() ########################################################################################### greetings Norbo |