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