Esempio n. 1
0
        /// <summary>
        /// Gets the instantiation block for a single blockram instance.
        /// </summary>
        /// <returns>The instantiation region.</returns>
        /// <param name="config">The configuration to generate the instantiation for.</param>
        /// <param name="instancename">The name of the encapsulating instance.</param>
        /// <param name="initialvalue">The initial value for the output</param>
        /// <param name="index">The instance index to use, or negative for no indexing</param>
        private string GetInstantiationRegion(BlockRamConfig config, string instancename, string initialvalue, IEnumerable <string> memdatalines, IEnumerable <string> pardatalines, int index = -1)
        {
            var memlines = string.Join(
                "," + Environment.NewLine,
                Enumerable.Range(0, int.MaxValue)
                .Zip(
                    memdatalines,
                    (a, b) => string.Format("    INIT_{0:X2} => X\"{1}\"", a, b)
                    )
                );

            var paritylines = string.Join(
                "," + Environment.NewLine,
                Enumerable.Range(0, int.MaxValue)
                .Zip(
                    pardatalines,
                    (a, b) => string.Format("    INITP_{0:X2} => X\"{1}\"", a, b)
                    )
                );

            var index_suffix = index < 0 ? string.Empty : $"_{index}";

            return
                ($@"
{instancename}_inst{index_suffix} : BRAM_SINGLE_MACRO
generic map (
    BRAM_SIZE => ""{(config.use36k ? "36Kb" : "18Kb")}"", -- Target BRAM, ""18Kb"" or ""36Kb""
    DEVICE => ""{ config.targetdevice }"", --Target device: ""VIRTEX5"", ""VIRTEX6"", ""7SERIES"", ""SPARTAN6""
    DO_REG => 0, --Optional output register(0 or 1)
    WRITE_WIDTH => { config.datawidth },    --Valid values are 1 - 72(37 - 72 only valid when BRAM_SIZE = ""36Kb"")
    READ_WIDTH => { config.datawidth },     --Valid values are 1 - 72(37 - 72 only valid when BRAM_SIZE = ""36Kb"")
    INIT_FILE => ""NONE"",
    SRVAL => X""{ initialvalue}"", --Set / Reset value for port output
    WRITE_MODE => ""READ_FIRST"", --Specify ""READ_FIRST"" for same clock or synchronous clocks
                               --  Specify ""WRITE_FIRST"" for asynchrononous clocks on ports

    -- The following INIT_xx declarations specify the initial contents of the RAM
{ memlines },

    -- The next set of INITP_xx are for the parity bits
{ paritylines },

    INIT => X""{ initialvalue}"" --Initial values on output port
)   
port map (
    DO => DO_internal{index_suffix},         -- Output read data port, width defined by READ_WIDTH parameter
    DI => DI_internal{index_suffix},         -- Input write data port, width defined by WRITE_WIDTH parameter
    ADDR => ADDR_internal{index_suffix},     -- Input address, width defined by read/write port depth    
    CLK => CLK,                -- 1-bit input clock
    EN => EN_internal{index_suffix},         -- 1-bit input enable
    REGCE => '0',              -- 1-bit input read output register enable
    RST => RST,                -- 1-bit input reset
    WE => WE_internal{index_suffix}          -- Input write enable, width defined by write port depth
);
-- End of BRAM_SINGLE_MACRO instantiation
");
        }
Esempio n. 2
0
        /// <summary>
        /// Gets a set of signals for communicating with a single blockram instance
        /// </summary>
        /// <returns>The signal region.</returns>
        /// <param name="config">The configuration to generate the signals for.</param>
        /// <param name="index">The instance index to use, or negative for no indexing</param>
        private string GetSignalRegion(BlockRamConfig config, int index = -1, int overrideAddrWidth = -1)
        {
            var index_suffix = index < 0 ? string.Empty : $"_{index}";

            return($@"
signal EN_internal{index_suffix}: std_logic;
signal WE_internal{index_suffix}: std_logic_vector({config.wewidth - 1} downto 0);
signal DI_internal{index_suffix}: std_logic_vector({config.datawidth - 1} downto 0);
signal DO_internal{index_suffix}: std_logic_vector({config.datawidth - 1} downto 0);
signal ADDR_internal{index_suffix}: std_logic_vector({(overrideAddrWidth <= 0 ? (config.realaddrwidth - 1) : (overrideAddrWidth - 1))} downto 0);
");
        }
Esempio n. 3
0
        public string BodyRegion(RenderStateProcess renderer, int indentation)
        {
            var initialdata = (Array)renderer.Process.SharedVariables.First(x => x.Name == "m_memory").DefaultValue;
            var size        = initialdata.Length;
            var datawidth   = VHDLHelper.GetBitWidthFromType(initialdata.GetType().GetElementType());

            var resetinitial = renderer.Process.LocalBusNames.Keys.Where(x => x.SourceType.Name == nameof(SME.Components.SinglePortMemory <int> .IReadResult)).SelectMany(x => x.Signals).First().DefaultValue;
            var initialvalue = VHDLHelper.GetDataBitString(initialdata.GetType().GetElementType(), resetinitial, datawidth);

            var itemsPr18k  = ((18 * 1024) + (datawidth - 1)) / datawidth;
            var in18kBlocks = (size + (itemsPr18k - 1)) / itemsPr18k;

            var fullAddressWidth = (int)Math.Ceiling(Math.Log(size, 2));

            var self   = renderer.Process;
            var outbus = self.OutputBusses.First();
            var inbus  = self.InputBusses.First();

            string signaltemplate;
            string instancetemplate;
            string gluetemplate;
            string clocktemplate;
            int    targetwidth;

            // Single 18k or single 36k item instantiation
            if (in18kBlocks <= 2)
            {
                var config = new BlockRamConfig(renderer, datawidth, datawidth * size, false);
                signaltemplate = GetSignalRegion(config, -1);

                var initlines = VHDLHelper.SplitDataBitStringToMemInit(
                    VHDLHelper.GetDataBitStrings(initialdata),
                    config.datawidth,
                    config.paritybits
                    );

                targetwidth      = config.realaddrwidth;
                instancetemplate = GetInstantiationRegion(config, renderer.Process.InstanceName, initialvalue, initlines.Item1, initlines.Item2, -1);
                gluetemplate     = string.Empty;
                clocktemplate    = string.Empty;
            }
            // Multi-unit instantiation
            else
            {
                var addrWidth    = (int)Math.Floor(Math.Log(((36 * 1024) + (datawidth - 1)) / datawidth, 2));
                var itemsPrBlock = (int)Math.Pow(2, addrWidth);
                var blocks       = (size + (itemsPrBlock - 1)) / itemsPrBlock;

                var sbsignals   = new System.Text.StringBuilder();
                var sbinstances = new System.Text.StringBuilder();
                var sbglue      = new System.Text.StringBuilder();

                var itemConfig = new BlockRamConfig(renderer, datawidth, itemsPrBlock * datawidth, true);
                sbsignals.Append(GetSignalRegion(itemConfig, -1, fullAddressWidth));
                sbsignals.AppendLine($"signal ADDR_READ_internal: std_logic_vector({fullAddressWidth - 1} downto 0);");

                for (var i = 0; i < blocks; i++)
                {
                    var config = new BlockRamConfig(renderer, datawidth, itemsPrBlock * datawidth, false);
                    sbsignals.Append(GetSignalRegion(config, i));

                    var initlines = VHDLHelper.SplitDataBitStringToMemInit(
                        VHDLHelper.GetDataBitStrings(initialdata, i * itemsPrBlock, itemsPrBlock),
                        config.datawidth,
                        config.paritybits
                        );

                    sbinstances.Append(GetInstantiationRegion(config, renderer.Process.InstanceName, initialvalue, initlines.Item1, initlines.Item2, i));

                    var indexAsBitString = VHDLHelper.GetDataBitString(i, fullAddressWidth - addrWidth);
                    indexAsBitString = indexAsBitString.Substring(indexAsBitString.Length - (fullAddressWidth - addrWidth));

                    sbglue.AppendLine($@"
EN_internal_{i} <= '1' when (EN_internal = '1') and (ADDR_internal({fullAddressWidth - 1} downto {addrWidth}) = ""{indexAsBitString}"") else '0';
WE_internal_{i} <= WE_internal;
DI_internal_{i} <= DI_internal;
ADDR_internal_{i} <= ADDR_internal({addrWidth - 1} downto 0);
");
                }

                // Create the output driver
                sbglue.AppendLine(GenerateOutputSelector(self.InstanceName, blocks, fullAddressWidth, addrWidth));

                targetwidth      = fullAddressWidth;
                signaltemplate   = sbsignals.ToString();
                instancetemplate = sbinstances.ToString();
                gluetemplate     = sbglue.ToString();
                clocktemplate    = "ADDR_READ_internal <= ADDR_internal;";
            }

            var template =
                $@"
{signaltemplate}

begin

{instancetemplate}

{self.InstanceName}_Helper: process(RST,CLK, RDY)
begin
if RST = '1' then
    FIN <= '0';                        
elsif rising_edge(CLK) then
    FIN <= not RDY;
    {clocktemplate}
end if;
end process;

{gluetemplate}

EN_internal <= ENB and {Naming.ToValidName(renderer.Parent.GetLocalBusName(inbus, self) + "_" + nameof(SME.Components.SinglePortMemory<int>.IControl.Enabled)) };
WE_internal <= (others => EN_internal and {Naming.ToValidName(renderer.Parent.GetLocalBusName(inbus, self) + "_" + nameof(SME.Components.SinglePortMemory<int>.IControl.IsWriting)) });
DI_internal <= std_logic_vector({ Naming.ToValidName(renderer.Parent.GetLocalBusName(inbus, self) + "_" + nameof(SME.Components.SinglePortMemory<int>.IControl.Data)) });
ADDR_internal <= std_logic_vector(resize(unsigned({ Naming.ToValidName(renderer.Parent.GetLocalBusName(inbus, self) + "_" + nameof(SME.Components.SinglePortMemory<int>.IControl.Address)) }), {targetwidth}));
{ Naming.ToValidName(renderer.Parent.GetLocalBusName(outbus, self) + "_" + nameof(SME.Components.SinglePortMemory<int>.IReadResult.Data)) } <= {renderer.Parent.VHDLWrappedTypeName(outbus.Signals.First())}(DO_internal);

";

            return(VHDLHelper.ReIndentTemplate(template, indentation));
        }
Esempio n. 4
0
        /// <summary>
        /// Gets the instantiation block for a single blockram instance.
        /// </summary>
        /// <returns>The instantiation region.</returns>
        /// <param name="config">The configuration to generate the instantiation for.</param>
        /// <param name="instancename">The name of the encapsulating instance.</param>
        /// <param name="initialvalue">The initial value for the output</param>
        /// <param name="index">The instance index to use, or negative for no indexing</param>
        private string GetInstantiationRegion(BlockRamConfig config, string instancename, string initialvalue, IEnumerable <string> memdatalines, IEnumerable <string> pardatalines, int index = -1)
        {
            var memlines = string.Join(
                "," + Environment.NewLine,
                Enumerable.Range(0, int.MaxValue)
                .Zip(
                    memdatalines,
                    (a, b) => string.Format("    INIT_{0:X2} => X\"{1}\"", a, b)
                    )
                );

            var paritylines = string.Join(
                "," + Environment.NewLine,
                Enumerable.Range(0, int.MaxValue)
                .Zip(
                    pardatalines,
                    (a, b) => string.Format("    INITP_{0:X2} => X\"{1}\"", a, b)
                    )
                );

            var index_suffix = index < 0 ? string.Empty : $"_{index}";

            return
                ($@"
{instancename}_inst{index_suffix} : BRAM_TDP_MACRO
generic map (
    BRAM_SIZE => ""{(config.use36k ? "36Kb" : "18Kb")}"", -- Target BRAM, ""18Kb"" or ""36Kb""
    DEVICE => ""{ config.targetdevice }"", --Target device: ""VIRTEX5"", ""VIRTEX6"", ""7SERIES"", ""SPARTAN6""
    DOA_REG => 0, --Optional port A output register(0 or 1)
    DOB_REG => 0, --Optional port B output register(0 or 1)
    INIT_FILE => ""NONE"",
    READ_WIDTH_A => { config.datawidth },     -- Valid values are 1 - 36(19 - 36 only valid when BRAM_SIZE = ""36Kb"")
    READ_WIDTH_B => { config.datawidth },     -- Valid values are 1 - 36(19 - 36 only valid when BRAM_SIZE = ""36Kb"")
    SIM_COLLISION_CHECK => ""GENERATE_X_ONLY"", --Collision check enable ""ALL"", ""WARNING_ONLY"",
                                 --""GENERATE_X_ONLY"" or ""NONE""
    SRVAL_A => X""{ initialvalue}"", --Set / Reset value for A port output
    SRVAL_B => X""{ initialvalue}"", --Set / Reset value for B port output
    WRITE_MODE_A => ""READ_FIRST"", -- ""WRITE_FIRST"", ""READ_FIRST"" or ""NO_CHANGE""
    WRITE_MODE_B => ""READ_FIRST"", -- ""WRITE_FIRST"", ""READ_FIRST"" or ""NO_CHANGE""
    WRITE_WIDTH_A => { config.datawidth },     -- Valid values are 1 - 36(19 - 36 only valid when BRAM_SIZE = ""36Kb"")
    WRITE_WIDTH_B => { config.datawidth },     -- Valid values are 1 - 36(19 - 36 only valid when BRAM_SIZE = ""36Kb"")

    -- The following INIT_xx declarations specify the initial contents of the RAM
{ memlines },

    -- The next set of INITP_xx are for the parity bits
{ paritylines },

    INIT_A => X""{ initialvalue}"", --Initial values on A output port
    INIT_B => X""{ initialvalue}""  --Initial values on B output port
)   
port map (
    DOA => DOA_internal{index_suffix},         -- Output port-A, width defined by READ_WIDTH_A parameter
    DOB => DOB_internal{index_suffix},         -- Output port-B, width defined by READ_WIDTH_B parameter
    ADDRA => ADDRA_internal{index_suffix},     -- Input port-A address, width defined by Port A depth
    ADDRB => ADDRB_internal{index_suffix},     -- Input port-B address, width defined by Port B depth
    CLKA => CLK,                 -- 1-bit input port-A clock
    CLKB => CLK,                 -- 1-bit input port-B clock
    DIA => DIA_internal{index_suffix},         -- Input port-A data, width defined by WRITE_WIDTH_A parameter
    DIB => DIB_internal{index_suffix},         -- Input port-B data, width defined by WRITE_WIDTH_B parameter
    ENA => ENA_internal{index_suffix},         -- 1-bit input port-A enable
    ENB => ENB_internal{index_suffix},         -- 1-bit input port-B enable
    REGCEA => '0',               -- 1-bit input port-A register enable
    REGCEB => '0',               -- 1-bit input port-B register enable
    RSTA => RST,                 -- 1-bit input port-A reset
    RSTB => RST,                 -- 1-bit input port-B reset
    WEA => WEA_internal{index_suffix},         -- Input port-A write enable, width defined by port A depth
    WEB => WEB_internal{index_suffix}          -- Input port-B write enable, width defined by port B depth
);
-- End of BRAM_TDP_MACRO_inst instantiation
");
        }