Re: [myhdl-list] Restrictions for conversion
Brought to you by:
jandecaluwe
From: Christopher F. <chr...@gm...> - 2012-04-20 16:23:16
|
As you are aware the use cases supported by MyHDL are RAM and ROM and examples for each and descriptions can be found here: http://www.myhdl.org/doc/0.7/manual/conversion_examples.html#ram-inference http://www.myhdl.org/doc/0.7/manual/conversion_examples.html#rom-inference What you are looking for is pre-initialize RAM, that is most notably used in FPGA designs. If you are only looking for ROM using a tuple of ints should get you what you want. It will load the correct examples. Your example below using the ROM template would convert to what you expect. # MyHDL description from myhdl import * def TOP(clk,out1,out2): rom = tuple([ii for ii in range(10)]) @always(clk.posedge) def rom_logic(): out1.next=rom[3] out2.next=rom[9] return rom_logic -- Converted VHDL TOP_ROM_LOGIC: process (clk) is begin if rising_edge(clk) then case 3 is when 0 => out1 <= "00000000"; when 1 => out1 <= "00000001"; when 2 => out1 <= "00000010"; when 3 => out1 <= "00000011"; when 4 => out1 <= "00000100"; when 5 => out1 <= "00000101"; when 6 => out1 <= "00000110"; when 7 => out1 <= "00000111"; when 8 => out1 <= "00001000"; when others => out1 <= "00001001"; end case; case 9 is when 0 => out2 <= "00000000"; when 1 => out2 <= "00000001"; when 2 => out2 <= "00000010"; when 3 => out2 <= "00000011"; when 4 => out2 <= "00000100"; when 5 => out2 <= "00000101"; when 6 => out2 <= "00000110"; when 7 => out2 <= "00000111"; when 8 => out2 <= "00001000"; when others => out2 <= "00001001"; end case; end if; end process TOP_ROM_LOGIC; In the past discussions the Altera recommended guidelines for RAM and ROM instantiation has been referenced. http://www.altera.com/literature/hb/qts/qts_qii51007.pdf. From my experience tool specific pragmas or init files are used to pre-init RAMS in the FPGA vendor tools. The guidelines for "specifying initial memory contents at power-up" is described start at section 11-32, which seem to suggest the same (.mif file). But it does go on to describe a method for initializing, using an initial block in Verilog and a function in VHDL. To get to an actual synthesizable approach it appears the initial values would not be enough? One of the reasons why initial values has not been implemented (it is on the todo list, http://www.myhdl.org/doku.php/dev:tasks#initial_values_suppot) is that it was observed that Quartus did not support initial value support in Verilog. There would be a mis-match between the Verilog conversion and VHDL conversion. It is not clear to me at this point what is the best path forward. I believe adding initial value support is possible just need to test with a bunch of tools, this is doable. If you actual goal is synthesiable pre-init RAM this path might not get you there. Regards, Chris On 4/20/12 8:16 AM, Norbo wrote: > I Considered the following example: > > from myhdl import * > > def TOP(out1,out2): > aListSig=[Signal(intbv(i)[8:]) for i in range(10)] > > @always_comb > def comb_logic(): > out1.next=aListSig[3] > out2.next=aListSig[9] > > return comb_logic > > > def test_bench(): > sig1=Signal(intbv(0)[8:]) > sig2=Signal(intbv(0)[8:]) > instanc_top=TOP(sig1,sig2) > > interval = delay(10) > @always(interval) > def stimulus(): > print "Value1 is: ",sig1," Value2 is: ",sig2 > > return stimulus,instanc_top > > > sim = Simulation(test_bench()) > sim.run(10) > toVHDL(TOP,Signal(intbv(0)[8:]),Signal(intbv(0)[8:] > > > > As expected the output of the simulation is: >>> Value1 is: 3 Value2 is: 9 > The genereted VHDL code however is: > > library IEEE; > use IEEE.std_logic_1164.all; > use IEEE.numeric_std.all; > use std.textio.all; > > use work.pck_myhdl_07.all; > > entity TOP is > port ( > out1: out unsigned(7 downto 0); > out2: out unsigned(7 downto 0) > ); > end entity TOP; > > architecture MyHDL of TOP is > > type t_array_aListSig is array(0 to 10-1) of unsigned(7 downto 0); > signal aListSig: t_array_aListSig; > > begin > > > > > > out1 <= aListSig(3); > out2 <= aListSig(9); > > end architecture MyHDL; > > this code obviously would not show these values at the ouput ports. > if in the myhdl code seperated signal instead of the list of signals is > used, > then the myhdl code would look like this: > > def TOP(out1,out2): > #aListSig=[Signal(intbv(i)[8:]) for i in range(10)] > aSig1=Signal(intbv(3)[8:]) > aSig2=Signal(intbv(9)[8:]) > > @always_comb > def comb_logic(): > out1.next=aSig1 #aListSig[3] > out2.next=aSig2 #aListSig[9] > > return comb_logic > > > > Then the generated in vhdl code looks like this: > > architecture MyHDL of TOP is > > signal aSig1: unsigned(7 downto 0); > signal aSig2: unsigned(7 downto 0); > > begin > > aSig1 <= to_unsigned(3, 8); > aSig2 <= to_unsigned(9, 8); > > > > > out1 <= aSig1; > out2 <= aSig2; > > end architecture MyHDL; > > In this example the values (3 and 9) are put on the output ports. > Do you see where i want to point at? > > > Now consider the case of a synchron Ram with pre-initialized values > which you want to infere, there the memory-list needs to have initial > values. > > from myhdl import * > > def sync_RAM(dout, din, addr, we, clk, CONTENT=None): > """sync Ram model """ > mem = [Signal(intbv(CONTENT[i],min=dout.min,max=dout.max)) for i in > range(len(CONTENT))] > > @always(clk.posedge) > def read_write(): > if we: > mem[addr].next = din > dout.next = mem[addr] > > return read_write > > def TESTBENCH_XX(): > we=Signal(bool()) > clk=Signal(bool()) > MemoryContent=[2,121,43,8,32]+range(3,10) > addr=Signal(intbv(0,min=0,max=len(MemoryContent))) > din=Signal(intbv(min(MemoryContent),min=min(MemoryContent),max=max(MemoryContent)+1 > )) > dout=Signal(intbv(min(MemoryContent),min=min(MemoryContent),max=max(MemoryContent)+1 > )) > > toVHDL(sync_RAM,dout,din,addr,we,clk,MemoryContent) > toVerilog(sync_RAM,dout,din,addr,we,clk,MemoryContent) > sync_RAM_inst=sync_RAM(dout,din,addr,we,clk,CONTENT=MemoryContent) > > @always(delay(10)) > def clkgen(): > clk.next = not clk > > @instance > def stimulus(): > for i,data in enumerate(MemoryContent): > addr.next=i > yield clk.negedge > print "Data is:", dout > > raise StopSimulation > > return sync_RAM_inst,clkgen,stimulus > > sim = Simulation(TESTBENCH_XX()) > sim.run() > > this is bassicaly very similar to the examples above where the > simulation has the initial values but the generated code > doesnt have them and therfore behaves different than the simulation. > Another thing is that you probably dont want to have every list of > signal which you declare in myhdl to be initialized in the generated code. > For that i used the "None" keyword of python e.g: > mem = [Signal(intbv(None)[8:]) for i in range(255)] > > So for me i basically changed the myhdl sources so that list of Signals > gets initialzed in the generated code, so the the above synchron RAM > descriptions gets converted to the following vhdl code: > > > library IEEE; > use IEEE.std_logic_1164.all; > use IEEE.numeric_std.all; > use std.textio.all; > > use work.pck_myhdl_07.all; > > entity sync_RAM is > port ( > dout: out unsigned(6 downto 0); > din: in unsigned(6 downto 0); > addr: in unsigned(3 downto 0); > we: in std_logic; > clk: in std_logic > ); > end entity sync_RAM; > -- Ram model > > architecture MyHDL of sync_RAM is > > type t_array_mem is array(0 to 12-1) of unsigned(6 downto 0); > signal mem: t_array_mem :=(0=>"0000010", > 1=>"1111001", > 2=>"0101011", > 3=>"0001000", > 4=>"0100000", > 5=>"0000011", > 6=>"0000100", > 7=>"0000101", > 8=>"0000110", > 9=>"0000111", > 10=>"0001000", > 11=>"0001001"); > > begin > > > > > SYNC_RAM_READ_WRITE: process (clk) is > begin > if rising_edge(clk) then > if to_boolean(we) then > mem(to_integer(addr)) <= din; > end if; > dout <= mem(to_integer(addr)); > end if; > end process SYNC_RAM_READ_WRITE; > > end architecture MyHDL; > > > > > > > > > And the generated Verilog code looks like this: > > > > > `timescale 1ns/10ps > > module sync_RAM ( > dout, > din, > addr, > we, > clk > ); > // Ram model > > output [6:0] dout; > reg [6:0] dout; > input [6:0] din; > input [3:0] addr; > input we; > input clk; > > > reg [6:0] mem [0:12-1]; > > initial > begin : INIT_mem > mem[0]=2; > mem[1]=121; > mem[2]=43; > mem[3]=8; > mem[4]=32; > mem[5]=3; > mem[6]=4; > mem[7]=5; > mem[8]=6; > mem[9]=7; > mem[10]=8; > mem[11]=9; > end > > > > > always @(posedge clk) begin: SYNC_RAM_READ_WRITE > if (we) begin > mem[addr] <= din; > end > dout <= mem[addr]; > end > > endmodule > > > I synthesised this syncron ram description in symplify and alter quartus > in vhdl and verilog and from the first view they both create the ram > with initial values succesfully > > if i change the the line: > mem = [Signal(intbv(CONTENT[i],min=dout.min,max=dout.max)) for i in > range(len(CONTENT))] > to: > mem = [Signal(intbv(None,min=dout.min,max=dout.max)) for i in > range(len(CONTENT))] > > then the code gets converted like normal, and in order to make the > boundchecks of the intbv succesfull i > set the initial value of the intbv to the lower bound value (min). if > this value is not given i set it to zero. > > > What you think about this? Have i overseen something important? Any > other suggestions? (if you want to try this, the patchfile should be > appended) > > greeting > Norbo > > > ------------------------------------------------------------------------------ > For Developers, A Lot Can Happen In A Second. > Boundary is the first to Know...and Tell You. > Monitor Your Applications in Ultra-Fine Resolution. Try it FREE! > http://p.sf.net/sfu/Boundary-d2dvs2 > > > > _______________________________________________ > myhdl-list mailing list > myh...@li... > https://lists.sourceforge.net/lists/listinfo/myhdl-list |