module HDLRuby::Low::Low2VHDL

Provides tools for converting HDLRuby::Low objects to VHDL.

Public Class Methods

alliance() click to toggle source

Tells if Allicance toolchain is targeted.

# File lib/HDLRuby/hruby_low2vhd.rb, line 44
def self.alliance
    return @@alliance
end
alliance=(mode) click to toggle source

Sets/unsets the Allicance toolchain targeting.

# File lib/HDLRuby/hruby_low2vhd.rb, line 49
def self.alliance=(mode)
    @@alliance = mode ? true : false
end
architecture_name(name) click to toggle source
Converts a +name+ to a VHDL architecture name.

NOTE: assume names have been converted to VHDL-compatible ones.

# File lib/HDLRuby/hruby_low2vhd.rb, line 122
def self.architecture_name(name)
    return self.vhdl_name(name.to_s + "_a")
end
arith?(type) click to toggle source

Tells if a type is arithmetic-compatible.

# File lib/HDLRuby/hruby_low2vhd.rb, line 127
def self.arith?(type)
    return type.is_a?(TypeVector) && 
        [:signed,:unsigned,:float].include?(type.base.name)
end
entity_name(name) click to toggle source
Converts a +name+ to a VHDL entity name.

NOTE: assume names have been converted to VHDL-compatible ones.

# File lib/HDLRuby/hruby_low2vhd.rb, line 115
def self.entity_name(name)
    return self.vhdl_name(name.to_s + "_e")
end
mux_function(type,num,spaces) click to toggle source

Generates the VHDL code for the mux function for type string tstr with num choices. spaces is the ident for the resulting code.

# File lib/HDLRuby/hruby_low2vhd.rb, line 297
def self.mux_function(type,num,spaces)
    # Create the strin of the type.
    tstr = type.to_vhdl
    # Create the name of the function from the type.
    name = mux_name(tstr,num)
    # Create the condition.
    if num == 2 then
        cond = "cond : boolean"
    else
        # First compute the width of the condition.
        width = (num-1).width
        # Now generate the condition.
        cond = "val : std_logic_vector(#{width-1} downto 0)"
    end
    # Generate the arguments.
    args = num.times.map {|i| "arg#{i} : #{tstr}" }.join("; ")
    # Generate the body.
    if num == 2 then
        body = "#{spaces}   if(cond) then\n" +
               "#{spaces}      return arg0;\n" +
               "#{spaces}   else\n" +
               "#{spaces}      return arg1;\n" +
               "#{spaces}   end if;\n"
    else
        # First compute the type of the choices.
        vtype = TypeVector.new(:"",Bit,width-1..0)
        # Now generate the body.
        body = "#{spaces}   case(val) is\n" +
            num.times.map do |i|
               pos = Value.new(vtype,i).to_vhdl
               "#{spaces}   when #{pos} => return arg#{i};\n"
            end.join + 
               "#{spaces}   end case;\n"
    end
    # Generate the choices.
    # Generates the function
    return "#{spaces}function #{name}" + 
               "(#{cond}; #{args})\n" +
           "#{spaces}return #{tstr} is\n" +
           "#{spaces}begin\n" + body +
           "#{spaces}end #{mux_name(tstr,num)};\n\n"
end
mux_name(tstr,num) click to toggle source

Generates the name of a mux function by type string tstr and number of arguments num.

# File lib/HDLRuby/hruby_low2vhd.rb, line 290
def self.mux_name(tstr,num)
    return "mux#{tstr.gsub(/[^a-zA-Z0-9_]/,"_")}#{num}"
end
packages(spaces) click to toggle source

Generates the pakage requirement for an entity. spaces are the spaces to put before each line.

# File lib/HDLRuby/hruby_low2vhd.rb, line 64
def self.packages(spaces)
    return "#{spaces}library ieee;\n" +
           "#{spaces}use ieee.std_logic_1164.all;\n" +
           "#{spaces}use ieee.numeric_std.all;\n\n"
end
to_arith(expr) click to toggle source

Generates expression expr while casting it to arithmetic-compatible type if required.

# File lib/HDLRuby/hruby_low2vhd.rb, line 134
def self.to_arith(expr)
    if arith?(expr.type) then
        # The expression is arithmetic-compatible, just generate it.
        if expr.is_a?(Value) then
            return expr.to_arith
        else
            return expr.to_vhdl
        end
    else
        # The expression is to convert, by default convert to unsigned
        # (this is the standard interpretation of HDLRuby).
        if expr.type.to_vhdl == "std_logic" then
            # std_logic case: must convert to vector first.
            if alliance then
                # Alliance toolchain case.
                return "unsigned('0' & " + expr.to_vhdl + ")"
            else
                # General case.
                return "unsigned(\"\" & " + expr.to_vhdl + ")"
            end
        else
            # Other case, ue the expression direction.
            return "unsigned(" + expr.to_vhdl + ")"
        end
    end
end
to_boolean(expr) click to toggle source

Generates a expression converted to the boolean type.

# File lib/HDLRuby/hruby_low2vhd.rb, line 192
def self.to_boolean(expr)
    # if boolean?(expr) then
    if expr.boolean? then
        # Comparison, no conversion required.
        return expr.to_vhdl
    else
        # Conversion to boolean required.
        return "(" + expr.to_vhdl + " = '1')"
    end
end
to_type(type,expr) click to toggle source

Generates epression expr while casting it to match type if required.

# File lib/HDLRuby/hruby_low2vhd.rb, line 205
def self.to_type(type,expr)
    # puts "expr=#{expr.to_vhdl}" unless expr.is_a?(Concat)
    # puts "type.width=#{type.width}, expr.type.width=#{expr.type.width}"
    if type.to_vhdl == "std_logic" then
        # Conversion to std_logic required.
        if expr.is_a?(Value) then
            # Values can simply be rewritten.
            if expr.content.to_s.to_i(2) == 0 then
                return "'0'"
            else
                return "'1'"
            end
        elsif expr.type.to_vhdl != "std_logic"
            # Otherwise a cast is required.
            # if expr.type.base.name == :signed then
            #     return "unsigned(#{expr.to_vhdl})(0)"
            # else
            #    # return "unsigned(#{expr.to_vhdl}(0))"
            #    return "unsigned(#{expr.to_vhdl})(0)"
            # end
            if alliance then
                # Specific syntax for casting to std_logic with Alliance
                if expr.type.width == 1 then
                    # No cast required with alliance if bitwidth is 1.
                    return expr.to_vhdl
                else
                    # Multi-bit, need to select a bit and possibly
                    # cast to unsigned.
                    if expr.type.signed? then
                        return "unsigned(#{expr.to_vhdl}(0))"
                    # elsif expr.is_a?(RefRange) then
                    #     # Range reference case.
                    #     return "#{expr.ref.to_vhdl}(#{expr.range.first.to_vhdl})"
                    else
                        # Other cases.
                        return "#{expr.to_vhdl}(0)"
                    end
                end
            else
                # Lint-compatible casting to std_logic
                if expr.type.signed? then
                    # Signed, cast to unsigned.
                    return "unsigned(#{expr.to_vhdl})(0)"
                # elsif expr.is_a?(RefRange) then
                #     # Range reference case.
                #     return "#{expr.ref.to_vhdl}(#{expr.range.first.to_vhdl})"
                else
                    # Other cases: for std_logic generation.
                    return expr.to_vhdl(0,true)
                end
            end
        else
            # Both are std_logic, nothing to to.
            return expr.to_vhdl
        end
    elsif expr.is_a?(Value) then
        # puts "type=#{type}, type.range=#{type.range}"
        # Value width must be adjusted.
        return expr.to_vhdl(0,false,type.width)
    elsif expr.is_a?(Concat) then
        return expr.to_vhdl(type)
    elsif expr.type.width < type.width then
        # Need to extend the type.
        return '"' + "0" * (type.width - expr.type.width) + '" & ' +
               expr.to_vhdl
    else 
        # No conversion required.
        return expr.to_vhdl
    end
end
unarith_cast(type) click to toggle source

Cast a type to undo arithmetic conversion if necessary.

# File lib/HDLRuby/hruby_low2vhd.rb, line 277
def self.unarith_cast(type)
    # Is the type arithmetic?
    if arith?(type) then
        # Yes, no undo required.
        return ""
    else
        # No, undo required.
        return "std_logic_vector"
    end
end
vhdl08() click to toggle source

Tells if VHDL'08 is supported or not.

# File lib/HDLRuby/hruby_low2vhd.rb, line 27
def self.vhdl08
    return @@vhdl08
end
vhdl08=(mode) click to toggle source

Sets/unsets the support of VHDL'08.

# File lib/HDLRuby/hruby_low2vhd.rb, line 32
def self.vhdl08=(mode)
    @@vhdl08 = mode ? true : false
end
vhdl_name(name) click to toggle source

Converts a name to a VHDL-compatible name.

# File lib/HDLRuby/hruby_low2vhd.rb, line 84
def self.vhdl_name(name)
    if vhdl08 then
        # VHDL'08, nothing to do if the name is VHDL-compatible.
        return name.to_s if self.vhdl_name?(name)
        # Otherwise put the name between //
        return "\\#{name}\\".to_s
    else
        # Not VHDL'08, need to mangle the name.
        # For safety also force downcase.
        name = name.to_s
        # Other letters: convert special characters.
        name = name.each_char.map do |c|
            if c=~ /[a-uw-z0-9]/ then
                c
            elsif c == "v" then
                "vv"
            else
                "v" + c.ord.to_s
            end
        end.join
        # First character: only letter is possible.
        unless name[0] =~ /[a-z]/ then
            name = "v" + name
        end
        return name
    end
end
vhdl_name?(name) click to toggle source

Tells if a name is VHDL-compatible. To ensure compatibile, assume all the character must have the same case.

# File lib/HDLRuby/hruby_low2vhd.rb, line 73
def self.vhdl_name?(name)
    name = name.to_s
    # First: character check.
    return false unless name =~ /^[a-zA-Z]|([a-zA-Z][a-zA-Z_0-9]*[a-zA-Z0-9])$/
    # Then character sequence check.
    return false if name.include?("__")
    # Then case check.
    return (name == name.upcase || name == name.downcase)
end
vhdl_string(str) click to toggle source

Converts string str to a VHDL-compatible string.

# File lib/HDLRuby/hruby_low2vhd.rb, line 55
def self.vhdl_string(str)
    str = str.gsub(/\n/,"\\n")
    str.gsub!(/\t/,"\\t")
    return str
end