lib/HDLRuby/hruby_verilog.rb in HDLRuby-3.0.0 vs lib/HDLRuby/hruby_verilog.rb in HDLRuby-3.1.0

- old
+ new

@@ -87,14 +87,14 @@ # Generate a truncer function name for expression of bit range +rngI+ using +rngS+ slice. def truncer_name(rngI,rngS) # Convert the ranges to arrays. rngI,rngS = self.r2a(rngI), self.r2a(rngS) # Generate the name. - return "trunc_#{rngI[0]}_#{rngI[1]}_#{rngS[0]}_#{rngS[1]}" + return "truncer_#{rngI[0]}_#{rngI[1]}_#{rngS[0]}_#{rngS[1]}" end - # Generate the truncating functionds. + # Generate the truncating functions. def dump # Ensure there is only one truncating function per range. @truncers.sort!.uniq! # Generate the resulting code. codeT = "" @@ -115,10 +115,57 @@ # Declaration of the truncating function generator. TruncersI = Truncers.new + # Class for generating the truncating functions in verilog. + # Such function are necessary as expression cannot be truncated directly. + class Indexers + def initialize + @indexers = [] + end + + # Add an indexer to of expression of verilog type +typI+ returning + # verilog type +typR+. + def add(typI,typR) + # Add them + @indexers << [typI,typR] + end + alias_method :<<, :add + + + # Generate an indexer function name for expression of verilog type + # +typI+ returning verilog type +typR+. + def indexer_name(typI,typR) + # Generate the name. + return "indexer_#{name_to_verilog(typI)}_#{name_to_verilog(typR)}" + end + + # Generate the indexing functions. + def dump + # Ensure there is only one indexing function per range. + @indexers.sort!.uniq! + # Generate the resulting code. + codeT = "" + @indexers.each do |(typI,typR)| + codeT << " function #{typR} " + codeT << self.indexer_name(typI,typR) + codeT << "(input #{typI} val, input integer idx);\n" + codeT << " " << self.indexer_name(typI,typR) << " = " + codeT << "val[idx];\n" + codeT << " endfunction\n\n" + end + # Clears the indexers. + @indexers = [] + return codeT + end + end + + # Declaration of the truncating function generator. + IndexersI = Indexers.new + + class Binary ## Enhances Binary with verilog generation. # Converts the system to Verilog code. def to_verilog @@ -1477,11 +1524,20 @@ class RefIndex ## Enhances RefIndex with generation of verilog code. # Converts the system to Verilog code. def to_verilog - return "#{self.ref.to_verilog}[#{self.index.to_verilog}]" + # return "#{self.ref.to_verilog}[#{self.index.to_verilog}]" + if self.ref.is_a?(RefName) then + return "#{self.ref.to_verilog}[#{self.index.to_verilog}]" + else + # No a pure signal, need to use a function for accessing. + at = self.ref.type.to_verilog + rt = self.type.to_verilog + IndexersI.add(at,rt) + return "#{IndexersI.indexer_name(at,rt)}(#{self.ref.to_verilog},#{self.index.to_verilog})" + end end end class TypeVector @@ -1503,11 +1559,19 @@ # Necessary for displaying bit width (eg, specify and assign). # Converts the system to Verilog code. def to_verilog(unknown = false) - return "#{self.ref.to_verilog}[#{self.range.first.to_getrange}:#{self.range.last.to_getrange}]" + if self.ref.is_a?(RefName) then + return "#{self.ref.to_verilog}[#{self.range.first.to_getrange}:#{self.range.last.to_getrange}]" + else + # No a pure signal, need to use a function for accessing. + sr = self.range.first.to_i..self.range.last.to_i + cr = (self.type.width-1)..0 + TruncersI.add(cr,sr) + return "#{TruncersI.truncer_name(cr,sr)}(#{self.ref.to_verilog})" + end end end class RefConcat @@ -1574,24 +1638,32 @@ # return "#{self.type.range.first + 1}'d#{str}" # end # end # return "#{self.type.range.first + 1}'b#{self.content.to_verilog}" if self.content.is_a?(Numeric) then - if self.content < 0 then - # str = (2**self.type.width + self.content).to_s(2) - str = self.content.to_s(2) - str = "0" * (self.type.width-str.length+1) + str[1..-1] - return "-#{self.type.width}'b#{str}" + if self.type.signed? then + if self.content < 0 then + # str = (2**self.type.width + self.content).to_s(2) + str = self.content.to_s(2) + str = "0" * (self.type.width-str.length+1) + str[1..-1] + return "-#{self.type.width}'sb#{str}" + else + str = self.content.to_s(2) + str = "0" * (self.type.width-str.length) + str + return "#{self.type.width}'sb#{str}" + end else - str = self.content.to_s(2) - str = "0" * (self.type.width-str.length) + str - return "#{self.type.width}'b#{str}" + return "#{self.type.width}'b#{self.content.to_s(2)}" end # return "#{self.type.width}'b#{str}" else str = self.content.to_verilog - return "#{str.length}'b#{str}" + if self.content.negative? then + return "#{str.length}'sb#{str}" + else + return "#{str.length}'b#{str}" + end end end # How to use when simply obtaining the width def to_getrange return "#{self.content.to_verilog}" @@ -1768,14 +1840,24 @@ end # Get the type widths, used for computing extensions or truncations. cw = self.child.type.width sw = self.type.width if self.type.signed? then - if (sw>cw) then - # Need to sign extend. - return "$signed({{#{sw-cw}{#{self.child.to_verilog}[#{cw-1}]}}," + - "#{self.child.to_verilog}})" + # Need to sign extend. + if cw == 1 then + return "$signed({#{sw}{#{self.child.to_verilog}}})" + elsif (sw>cw) then + # return "$signed({{#{sw-cw}{#{self.child.to_verilog}[#{cw-1}]}}," + "#{self.child.to_verilog}})" + if self.child.is_a?(RefName) then + return "$signed({{#{sw-cw}{#{self.child.to_verilog}[#{cw-1}]}}," + "#{self.child.to_verilog}})" + else + # No a pure signal, need to use a function for accessing. + at = self.child.type.to_verilog + rt = bit.to_verilog + IndexersI.add(at,rt) + return "$signed({{#{sw-cw}{#{IndexersI.indexer_name(at,rt)}(#{self.child.to_verilog},#{cw-1})}}," + "#{self.child.to_verilog}})" + end elsif (sw<cw) then # Need to truncate # return "$signed(#{self.child.to_verilog}[#{sw-1}:0])" TruncersI.add((cw-1)..0,(sw-1)..0) return "$signed(#{TruncersI.truncer_name((cw-1)..0,(sw-1)..0)}(#{self.child.to_verilog}))" @@ -2286,9 +2368,11 @@ # Conclusion. codeC << "\nendmodule" # Adds the truncing functions. code << TruncersI.dump + # Adds the indexing functions. + code << IndexersI.dump # Adds the content code. code << codeC return code end end