Re: [myhdl-list] Restrictions for conversion
Brought to you by:
jandecaluwe
From: Norbo <Nor...@gm...> - 2012-04-20 13:16:54
|
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 |