Module: HDLRuby::Low::Low2VHDL
- Defined in:
- lib/HDLRuby/hruby_low2vhd.rb
Overview
Provides tools for converting HDLRuby::Low objects to VHDL.
Constant Summary collapse
- @@vhdl08 =
Indicates if VHDL'08 can be generated. Default: true
NOTE: when possible, it is better to be left true since the identifier does not require any mangling in VHDL'08
true
- @@alliance =
Indicates if target toolchain is Alliance: requires a slightly different VHDL syntax.
NOTE: this syntax is not lint-compatible and should be avoided unless using specifically Alliance.
false
Class Method Summary collapse
-
.alliance ⇒ Object
Tells if Allicance toolchain is targeted.
-
.alliance=(mode) ⇒ Object
Sets/unsets the Allicance toolchain targeting.
-
.architecture_name(name) ⇒ Object
Converts a +name+ to a VHDL architecture name.
-
.arith?(type) ⇒ Boolean
Tells if a +type+ is arithmetic-compatible.
-
.entity_name(name) ⇒ Object
Converts a +name+ to a VHDL entity name.
-
.mux_function(type, num, spaces) ⇒ Object
Generates the VHDL code for the mux function for type string +tstr+ with +num+ choices.
-
.mux_name(tstr, num) ⇒ Object
Generates the name of a mux function by type string +tstr+ and number of arguments +num+.
-
.packages(spaces) ⇒ Object
Generates the pakage requirement for an entity.
-
.to_arith(expr) ⇒ Object
Generates expression +expr+ while casting it to arithmetic-compatible type if required.
-
.to_boolean(expr) ⇒ Object
Generates a expression converted to the boolean type.
-
.to_type(type, expr) ⇒ Object
Generates epression +expr+ while casting it to match +type+ if required.
-
.unarith_cast(type) ⇒ Object
Cast a +type+ to undo arithmetic conversion if necessary.
-
.vhdl08 ⇒ Object
Tells if VHDL'08 is supported or not.
-
.vhdl08=(mode) ⇒ Object
Sets/unsets the support of VHDL'08.
-
.vhdl_name(name) ⇒ Object
Converts a +name+ to a VHDL-compatible name.
-
.vhdl_name?(name) ⇒ Boolean
Tells if a +name+ is VHDL-compatible.
Class Method Details
.alliance ⇒ Object
Tells if Allicance toolchain is targeted.
44 45 46 |
# File 'lib/HDLRuby/hruby_low2vhd.rb', line 44 def self.alliance return @@alliance end |
.alliance=(mode) ⇒ Object
Sets/unsets the Allicance toolchain targeting.
49 50 51 |
# File 'lib/HDLRuby/hruby_low2vhd.rb', line 49 def self.alliance=(mode) @@alliance = mode ? true : false end |
.architecture_name(name) ⇒ Object
Converts a +name+ to a VHDL architecture name.
NOTE: assume names have been converted to VHDL-compatible ones.
113 114 115 |
# File 'lib/HDLRuby/hruby_low2vhd.rb', line 113 def self.architecture_name(name) return self.vhdl_name(name.to_s + "_a") end |
.arith?(type) ⇒ Boolean
Tells if a +type+ is arithmetic-compatible.
118 119 120 121 |
# File 'lib/HDLRuby/hruby_low2vhd.rb', line 118 def self.arith?(type) return type.is_a?(TypeVector) && [:signed,:unsigned,:float].include?(type.base.name) end |
.entity_name(name) ⇒ Object
Converts a +name+ to a VHDL entity name.
NOTE: assume names have been converted to VHDL-compatible ones.
106 107 108 |
# File 'lib/HDLRuby/hruby_low2vhd.rb', line 106 def self.entity_name(name) return self.vhdl_name(name.to_s + "_e") end |
.mux_function(type, num, spaces) ⇒ Object
Generates the VHDL code for the mux function for type string +tstr+ with +num+ choices. +spaces+ is the ident for the resulting code.
288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 |
# File 'lib/HDLRuby/hruby_low2vhd.rb', line 288 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) ⇒ Object
Generates the name of a mux function by type string +tstr+ and number of arguments +num+.
281 282 283 |
# File 'lib/HDLRuby/hruby_low2vhd.rb', line 281 def self.mux_name(tstr,num) return "mux#{tstr.gsub(/[^a-zA-Z0-9_]/,"_")}#{num}" end |
.packages(spaces) ⇒ Object
Generates the pakage requirement for an entity. +spaces+ are the spaces to put before each line.
55 56 57 58 59 |
# File 'lib/HDLRuby/hruby_low2vhd.rb', line 55 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) ⇒ Object
Generates expression +expr+ while casting it to arithmetic-compatible type if required.
125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 |
# File 'lib/HDLRuby/hruby_low2vhd.rb', line 125 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) ⇒ Object
Generates a expression converted to the boolean type.
183 184 185 186 187 188 189 190 191 192 |
# File 'lib/HDLRuby/hruby_low2vhd.rb', line 183 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) ⇒ Object
Generates epression +expr+ while casting it to match +type+ if required.
196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 |
# File 'lib/HDLRuby/hruby_low2vhd.rb', line 196 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) ⇒ Object
Cast a +type+ to undo arithmetic conversion if necessary.
268 269 270 271 272 273 274 275 276 277 |
# File 'lib/HDLRuby/hruby_low2vhd.rb', line 268 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 ⇒ Object
Tells if VHDL'08 is supported or not.
27 28 29 |
# File 'lib/HDLRuby/hruby_low2vhd.rb', line 27 def self.vhdl08 return @@vhdl08 end |
.vhdl08=(mode) ⇒ Object
Sets/unsets the support of VHDL'08.
32 33 34 |
# File 'lib/HDLRuby/hruby_low2vhd.rb', line 32 def self.vhdl08=(mode) @@vhdl08 = mode ? true : false end |
.vhdl_name(name) ⇒ Object
Converts a +name+ to a VHDL-compatible name.
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 |
# File 'lib/HDLRuby/hruby_low2vhd.rb', line 75 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) ⇒ Boolean
Tells if a +name+ is VHDL-compatible. To ensure compatibile, assume all the character must have the same case.
64 65 66 67 68 69 70 71 72 |
# File 'lib/HDLRuby/hruby_low2vhd.rb', line 64 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 |