verilog_gen 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +4 -0
- data/README.md +22 -1
- data/Rakefile +20 -0
- data/bin/hdl_equal +82 -0
- data/bin/vgen +57 -1
- data/bin/vscan +354 -0
- data/demos/router/Makefile +11 -0
- data/demos/router/build/chip1_router.rb +50 -0
- data/demos/router/build/chip2_router.rb +33 -0
- data/demos/router/build/generic_router.rb +96 -0
- data/demos/router/rtl/fifo_ctrl.v +93 -0
- data/demos/router/rtl/flop_delay.v +37 -0
- data/demos/router/rtl/generic_mem.v +38 -0
- data/demos/router/rtl/router_ctrl.v +73 -0
- data/demos/router/rtl/rr_arb.v +55 -0
- data/demos/router/vendors/vendor1/mem_16nm_bist_ctrl.v +56 -0
- data/demos/router/vendors/vendor1/mem_16nm_ram4x64.v +50 -0
- data/demos/router/vendors/vendor1/mem_16nm_ram8x64.v +50 -0
- data/demos/router/vendors/vendor2/mem_16nm_bist_ctrl.v +56 -0
- data/demos/router/vendors/vendor2/mem_16nm_ram12x73.v +50 -0
- data/demos/router/vendors/vendor2/mem_16nm_ram4x73.v +50 -0
- data/docs/demo.md +142 -0
- data/docs/sst.md +76 -0
- data/features/cucumber.yml +1 -0
- data/features/hdl_equal/hello.feature +9 -0
- data/features/hdl_equal/leaf_compare.feature +11 -0
- data/features/hdl_equal/neg_compare.feature +17 -0
- data/features/hdl_equal/port_width_compare.feature +17 -0
- data/features/sprint1/hello.feature +9 -0
- data/features/sprint1/hier_connect_1.feature +81 -0
- data/features/sprint1/hier_connect_2.feature +91 -0
- data/features/sprint1/hier_connect_3.feature +90 -0
- data/features/sprint1/inhibit_port.feature +41 -0
- data/features/sprint1/input_connect.feature +79 -0
- data/features/sprint1/leaf_rename.feature +41 -0
- data/features/sprint1/new_leaf_design.erb +52 -0
- data/features/sprint1/output_connect.feature +79 -0
- data/features/sprint1/regex_port_rewrites.feature +43 -0
- data/features/sprint1/subrange_port.feature +43 -0
- data/features/sprint1/swap_leaf.feature +122 -0
- data/features/sprint1/tie_port.feature +40 -0
- data/features/sprint1/unused_port.feature +41 -0
- data/features/sprint1/vector_split.feature +41 -0
- data/features/sprint1/wire_connect.feature +46 -0
- data/features/sprint2/expression_net.feature +41 -0
- data/features/sprint2/fifo.feature +61 -0
- data/features/sprint2/wire_expression.feature +48 -0
- data/features/step_definitions/vgen_steps.rb +3 -0
- data/features/support/env.rb +3 -1
- data/features/vgen/add_child.feature +60 -0
- data/features/vgen/fifo_ctrl.feature +24 -0
- data/features/vgen/hello.feature +9 -0
- data/features/vgen/leaf_node.feature +15 -0
- data/features/vgen/output_dir.feature +19 -0
- data/features/vgen/simple_node.feature +24 -0
- data/features/vgen/thin_hookup.feature +22 -0
- data/features/vscan/bad_path.feature +9 -0
- data/features/vscan/class_override.feature +23 -0
- data/features/vscan/class_override_path.feature +23 -0
- data/features/vscan/complex_expressions.feature +47 -0
- data/features/vscan/data_types_2001.feature +36 -0
- data/features/vscan/data_types_sv.feature +53 -0
- data/features/vscan/hello.feature +9 -0
- data/features/vscan/hiearchy_path.feature +23 -0
- data/features/vscan/illegal_argument.feature +9 -0
- data/features/vscan/inout.feature +23 -0
- data/features/vscan/interface_nested.feature +53 -0
- data/features/vscan/interface_nested_no_out.feature +48 -0
- data/features/vscan/interface_param_default.feature +41 -0
- data/features/vscan/interface_param_override.feature +27 -0
- data/features/vscan/interface_port.feature +41 -0
- data/features/vscan/interface_sv.feature +35 -0
- data/features/vscan/leaf_1995.feature +27 -0
- data/features/vscan/leaf_2001.feature +25 -0
- data/features/vscan/leaf_negative_1995.feature +24 -0
- data/features/vscan/leaf_sv.feature +25 -0
- data/features/vscan/localparam_2001.feature +38 -0
- data/features/vscan/missing_parameter.feature +24 -0
- data/features/vscan/multiple_class.feature +9 -0
- data/features/vscan/multiple_flavors.feature +64 -0
- data/features/vscan/multiple_modules.feature +60 -0
- data/features/vscan/name_mismatch.feature +24 -0
- data/features/vscan/net_type.feature +67 -0
- data/features/vscan/parameter_override.feature +43 -0
- data/features/vscan/parameters_1995.feature +43 -0
- data/features/vscan/parameters_2001.feature +38 -0
- data/features/vscan/read_only.feature +19 -0
- data/features/vscan/reverse_vectors_1995.feature +33 -0
- data/features/vscan/single_line_1995.feature +24 -0
- data/features/vscan/vectors_1995.feature +33 -0
- data/features/vscan/vectors_2001.feature +29 -0
- data/features/vscan/vectors_sv.feature +31 -0
- data/lib/templates/helpers.rb +85 -0
- data/lib/templates/v2k_template.erb +6 -0
- data/lib/verilog_gen.rb +8 -3
- data/lib/verilog_gen/hdl_module.rb +274 -0
- data/lib/verilog_gen/hookup.rb +153 -0
- data/lib/verilog_gen/pin.rb +39 -0
- data/lib/verilog_gen/port.rb +109 -0
- data/lib/verilog_gen/proxy.rb +33 -0
- data/lib/verilog_gen/string.rb +38 -0
- data/lib/verilog_gen/version.rb +1 -1
- data/spec/fixture/generic_mem.v +38 -0
- data/spec/hdl_child_array_spec.rb +29 -0
- data/spec/hdl_hier_spec.rb +45 -0
- data/spec/hdl_hookup.spec +37 -0
- data/spec/hdl_module_spec.rb +117 -0
- data/spec/hdl_output_spec.rb +88 -0
- data/spec/hdl_port_spec.rb +35 -0
- data/spec/hdl_remove_child.spec +37 -0
- data/spec/pin_spec.rb +37 -0
- data/spec/port_spec.rb +90 -0
- data/spec/proxy_spec.rb +41 -0
- data/spec/spec_helper.rb +2 -0
- data/verilog_gen.gemspec +1 -1
- metadata +194 -8
- data/features/hello.feature +0 -8
- data/features/support/aruba.rb +0 -1
@@ -0,0 +1,153 @@
|
|
1
|
+
module VerilogGen
|
2
|
+
|
3
|
+
# Check if all the ports in the list are inputs.
|
4
|
+
# @param [Array] port_lst is the list of ports
|
5
|
+
# @return [Boolean] True if all are inputs.
|
6
|
+
def self.unconnected_input_ports?(port_lst)
|
7
|
+
return false if port_lst.empty?
|
8
|
+
port_lst.each do |port|
|
9
|
+
return false unless port.direction == "input"
|
10
|
+
end
|
11
|
+
return true
|
12
|
+
end
|
13
|
+
|
14
|
+
# Check if all the ports in the list are outputs.
|
15
|
+
# @param [Array] port_lst is the list of ports
|
16
|
+
# @return [Boolean] True if all are outputs.
|
17
|
+
def self.unconnected_output_ports?(port_lst)
|
18
|
+
return false if port_lst.empty?
|
19
|
+
port_lst.each do |port|
|
20
|
+
return false unless port.direction == "output"
|
21
|
+
end
|
22
|
+
return true
|
23
|
+
end
|
24
|
+
|
25
|
+
# Find the super width from a list of ports.
|
26
|
+
# @param [Array] list of ports
|
27
|
+
# @return [Array] lhs, rhs
|
28
|
+
# @note:
|
29
|
+
# Assumes that all ports in the list are of same endiannes..
|
30
|
+
# FIXME: For this it looks at the port in the middle.
|
31
|
+
# Should scan all the ports to detect it.
|
32
|
+
def self.super_port_width(port_lst)
|
33
|
+
sample_port = port_lst[port_lst.size/2]
|
34
|
+
lhs_values = []
|
35
|
+
rhs_values = []
|
36
|
+
port_lst.each do |port|
|
37
|
+
lhs_values << port.lhs
|
38
|
+
rhs_values << port.rhs
|
39
|
+
end
|
40
|
+
if sample_port.lhs > sample_port.rhs
|
41
|
+
return lhs_values.max, rhs_values.min
|
42
|
+
else
|
43
|
+
return lhs_values.min, rhs_values.max
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# Adds a connect port to the hdl module class.
|
48
|
+
# @return nil
|
49
|
+
# @note The name of the connect port is the name of the pin
|
50
|
+
# and the width of the port is the super width.
|
51
|
+
def self.add_new_connect_port(klass, pin_name, port_lst)
|
52
|
+
lhs, rhs = super_port_width(port_lst)
|
53
|
+
p = port_lst[0].create_connect_port(pin_name, lhs, rhs)
|
54
|
+
klass.ports[pin_name] = p
|
55
|
+
end
|
56
|
+
|
57
|
+
# Create pins for unconnected ports in current instance.
|
58
|
+
# @param [Object] instance of hdl module
|
59
|
+
# @return [Fixnum] Number of pins added
|
60
|
+
# @note Ports with existing pins are skippped.
|
61
|
+
def self.create_missing_pins(instance)
|
62
|
+
num_pins_created = 0
|
63
|
+
instance.class.ports.each do |port_name, port|
|
64
|
+
unless instance.pins.key? port_name
|
65
|
+
instance.pins[port_name] = Pin.new(port)
|
66
|
+
num_pins_created += 1
|
67
|
+
end
|
68
|
+
end
|
69
|
+
num_pins_created
|
70
|
+
end
|
71
|
+
|
72
|
+
# Create missing pins for all children below the instance.
|
73
|
+
# Use depth first to build all the leaf and then the rest of the
|
74
|
+
# modules.
|
75
|
+
# @param [Object] instance of the design.
|
76
|
+
# @return [nil]
|
77
|
+
# @note Idempotent since port that have pins are skipped.
|
78
|
+
def self.create_missing_pins_depth_first(instance)
|
79
|
+
if instance.class.proxy
|
80
|
+
# Leaf do not change the ports. hence we don't need to do it again.
|
81
|
+
# But it is harmless if all ports are already connected.
|
82
|
+
create_missing_pins instance
|
83
|
+
else
|
84
|
+
instance.class.child_instances.each do |child_name, child|
|
85
|
+
create_missing_pins_depth_first child
|
86
|
+
end
|
87
|
+
# If new pins are created then we would need to create the connect ports
|
88
|
+
# in the current class.
|
89
|
+
num_new_ports = create_connect_ports(instance.class)
|
90
|
+
|
91
|
+
# Run custom user connect
|
92
|
+
instance.class.connect
|
93
|
+
|
94
|
+
# If we added new ports to the class then all instantiaton must get new pins.
|
95
|
+
create_missing_pins instance if num_new_ports > 0
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
# Create connectivity map for children of a hdl module.
|
100
|
+
# @param [Object] klass of the hdl module.
|
101
|
+
# @return [Hash] hash of array. PinName => [Port0, Port 10.....]
|
102
|
+
#
|
103
|
+
def self.get_child_pins_connectivity(klass)
|
104
|
+
pin_connections = Hash.new {|hash, key| hash[key] = Array.new }
|
105
|
+
klass.child_instances.each do |child_name, child|
|
106
|
+
child.pins.each do |port_name, pin|
|
107
|
+
pin_connections[pin.name].push pin.port
|
108
|
+
end
|
109
|
+
end
|
110
|
+
pin_connections
|
111
|
+
end
|
112
|
+
|
113
|
+
# Create ports to provide connectivity to the child instances.
|
114
|
+
# @param [Object] klass HdlModule
|
115
|
+
# @return [Fixnum] number of ports created in the class.
|
116
|
+
# @note
|
117
|
+
# An input port is created if the children pins are inputs.
|
118
|
+
# A output port is created if the children pins are output.
|
119
|
+
# If mixture of input and output pins, then no ports are created.
|
120
|
+
# The width of the port is the superset of the width.
|
121
|
+
def self.create_connect_ports(klass)
|
122
|
+
num_connect_ports = 0
|
123
|
+
pin_connections = get_child_pins_connectivity(klass)
|
124
|
+
pin_connections.each do |pin_name, port_lst|
|
125
|
+
if unconnected_input_ports?(port_lst)
|
126
|
+
add_new_connect_port(klass, pin_name, port_lst)
|
127
|
+
num_connect_ports += 1
|
128
|
+
elsif unconnected_output_ports?(port_lst)
|
129
|
+
add_new_connect_port(klass, pin_name, port_lst)
|
130
|
+
num_connect_ports += 1
|
131
|
+
end
|
132
|
+
end
|
133
|
+
num_connect_ports
|
134
|
+
end
|
135
|
+
|
136
|
+
# Connect child instances and create hookup ports.
|
137
|
+
# @param [Object] top_level_class of the design.
|
138
|
+
# @note
|
139
|
+
# Start with each child instance.
|
140
|
+
#
|
141
|
+
def self.hookup(top_level_class)
|
142
|
+
top_level_class.child_instances.each do |instance_name, instance|
|
143
|
+
create_missing_pins_depth_first(instance)
|
144
|
+
end
|
145
|
+
# Run custom user connect
|
146
|
+
top_level_class.connect
|
147
|
+
|
148
|
+
# Create the primary connect ports
|
149
|
+
create_connect_ports(top_level_class)
|
150
|
+
|
151
|
+
end
|
152
|
+
|
153
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module VerilogGen
|
2
|
+
# Model of a pin connected to a port
|
3
|
+
class Pin
|
4
|
+
|
5
|
+
attr_reader :port, :name, :type, :lhs, :rhs, :direction
|
6
|
+
|
7
|
+
# A pin connects to a port.
|
8
|
+
# @note By default the pin name, type and width is the same as port.
|
9
|
+
def initialize(port)
|
10
|
+
@port = port
|
11
|
+
@name = port.name
|
12
|
+
@type = port.type
|
13
|
+
@lhs = port.lhs
|
14
|
+
@rhs = port.rhs
|
15
|
+
@direction = port.direction
|
16
|
+
end
|
17
|
+
|
18
|
+
# Update a pin attributes.
|
19
|
+
# @param [String] name of the pin
|
20
|
+
# @param [Hash] params properties of pin
|
21
|
+
# @option params [String] :name of the pin
|
22
|
+
# @option params [String] :type of the pin
|
23
|
+
# @option params [Fixnum] :lhs left hand width of the pin
|
24
|
+
# @option params [Fixnum] :rhs right hand width of the pin
|
25
|
+
# @option params [String] :direction of the pin
|
26
|
+
def connect(pin_name, params = {})
|
27
|
+
@name = pin_name
|
28
|
+
params.each do |key, value|
|
29
|
+
raise ArgumentError, "Unknown attribute '#{key}' specified for pin" \
|
30
|
+
unless instance_variables.include?("@#{key}".to_sym)
|
31
|
+
instance_variable_set("@#{key}", value)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def width
|
36
|
+
(@lhs - @rhs + 1).abs
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
module VerilogGen
|
2
|
+
# Model of a verilog port.
|
3
|
+
class Port
|
4
|
+
|
5
|
+
@@DEFAULT_PARAMS = {
|
6
|
+
:name => "",
|
7
|
+
:direction => "input",
|
8
|
+
:lhs => 0,
|
9
|
+
:rhs => 0,
|
10
|
+
:type => "wire",
|
11
|
+
:packed => "",
|
12
|
+
:unpacked => ""
|
13
|
+
}
|
14
|
+
|
15
|
+
# Construct a port.
|
16
|
+
# @param [Hash] params properties of the port
|
17
|
+
# @option params [String] :name name of the port
|
18
|
+
# @option params [String] :direction By default input
|
19
|
+
# @option params [Integer]:left By default 0
|
20
|
+
# @option params [Integer] right hand digit. By default 0.
|
21
|
+
# @note If lhs and rhs are 0 then it is a scalar port else vector type.
|
22
|
+
def initialize(name, params = {})
|
23
|
+
@@DEFAULT_PARAMS.each do |key, value|
|
24
|
+
instance_variable_set("@#{key}", value)
|
25
|
+
self.class.send(:attr_reader, key.to_s)
|
26
|
+
end
|
27
|
+
|
28
|
+
@name = name
|
29
|
+
|
30
|
+
params.each do |key, value|
|
31
|
+
raise ArgumentError,
|
32
|
+
"invalid value of port field '#{key}' with '#{value}'" \
|
33
|
+
unless @@DEFAULT_PARAMS.has_key? key
|
34
|
+
instance_variable_set("@#{key}", value)
|
35
|
+
end
|
36
|
+
|
37
|
+
#Enumeration checking.
|
38
|
+
raise ArgumentError, "direction '#{direction}' is not valid value" \
|
39
|
+
unless @direction == "input" or @direction == "output"\
|
40
|
+
or @direction == "inout"
|
41
|
+
|
42
|
+
# FIXME: Hack lhs and rhs
|
43
|
+
unless @packed == ""
|
44
|
+
m = /\[\s*(-*\d+)\s*:\s*(-*\d+)\s*\]/.match @packed
|
45
|
+
@lhs = m.captures[0].to_i
|
46
|
+
@rhs = m.captures[1].to_i
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# Equaltiy of port
|
51
|
+
# @param [Object] other port instance
|
52
|
+
# @return [Boolean] comparion result
|
53
|
+
def ==(other)
|
54
|
+
return false unless other.instance_of?(self.class)
|
55
|
+
name == other.name && direction == other.direction \
|
56
|
+
&& lhs == other.lhs && rhs == other.rhs
|
57
|
+
end
|
58
|
+
|
59
|
+
# Well behaved hash keys
|
60
|
+
# @param [Object] other port instance
|
61
|
+
# @return [Boolean] true/false
|
62
|
+
# @note if a.eql?(b) then a.hash = b.hash
|
63
|
+
def eql?(other)
|
64
|
+
return self == other
|
65
|
+
end
|
66
|
+
|
67
|
+
# Compute the hash key.
|
68
|
+
def hash
|
69
|
+
return name.hash ^ direction.hash ^ lhs.hash ^ rhs.hash
|
70
|
+
end
|
71
|
+
|
72
|
+
# Utility function to detect scalar vector port.
|
73
|
+
# @return [Boolean] true if this is a scalar port else vector.
|
74
|
+
# @note A port is scalar if lhs and rhs are both 0.
|
75
|
+
def scalar?
|
76
|
+
lhs == 0 and rhs == 0
|
77
|
+
end
|
78
|
+
|
79
|
+
# Utility function to return the width of the port
|
80
|
+
# @return [Integer] Width of the port
|
81
|
+
def width
|
82
|
+
(lhs > rhs) ? lhs - rhs + 1 : rhs - lhs + 1
|
83
|
+
end
|
84
|
+
|
85
|
+
# Utility routine to return the port declaration
|
86
|
+
# @return [String]
|
87
|
+
def type
|
88
|
+
if direction == "output" and width == 1
|
89
|
+
return "logic"
|
90
|
+
elsif direction == "output"
|
91
|
+
return "logic [#{lhs}:#{rhs}]"
|
92
|
+
elsif direction == "input" and not scalar?
|
93
|
+
return "[#{lhs}:#{rhs}]"
|
94
|
+
else
|
95
|
+
return ""
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
# HACK for creating a connect port.
|
100
|
+
# Want to create a port that is identical to the current port but
|
101
|
+
# has a different name and width.
|
102
|
+
# @note : This is a hack for getting the demo to work.
|
103
|
+
def create_connect_port(new_name, new_lhs, new_rhs)
|
104
|
+
p = Port.new(new_name, direction: direction,
|
105
|
+
lhs: new_lhs , rhs: new_rhs, type: type,
|
106
|
+
packed: "", unpacked: "")
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# Wrapper routines to import design into ruby.
|
2
|
+
|
3
|
+
module VerilogGen
|
4
|
+
# Return the created class for subsequent access.
|
5
|
+
@@verilog_leaf_created = {}
|
6
|
+
|
7
|
+
# Invoke vscan to create the leaf proxy.
|
8
|
+
# @param [String] Class name of hdl leaf.
|
9
|
+
# @param [Hash] parameter to pass to vscan.
|
10
|
+
# @param file_name [Hash] name of the rtl file.
|
11
|
+
# @return Hdl module class.
|
12
|
+
# @note
|
13
|
+
# Once a class is created then subsequent access will return prev value.
|
14
|
+
def self.leaf(klass, params = {})
|
15
|
+
options = { parameter: "", file_name: klass.snakecase + ".v" }
|
16
|
+
params.each do |key, value|
|
17
|
+
raise ArgumentError, "invalid valid value of leaf '#{key}'" \
|
18
|
+
unless options.key? key
|
19
|
+
options[key] = params[key]
|
20
|
+
end
|
21
|
+
|
22
|
+
key = klass + options[:parameter]
|
23
|
+
unless @@verilog_leaf_created.key?(key)
|
24
|
+
puts "Running vscan #{options[:parameter]} -class #{klass} #{options[:file_name]}"
|
25
|
+
output = `vscan #{options[:parameter]} -class #{klass} \
|
26
|
+
#{options[:file_name]}`
|
27
|
+
eval output, binding, __FILE__, __LINE__
|
28
|
+
@@verilog_leaf_created[key] = Object.const_get("VerilogGen::#{klass}")
|
29
|
+
end
|
30
|
+
@@verilog_leaf_created[key]
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
@@ -0,0 +1,38 @@
|
|
1
|
+
class String
|
2
|
+
def camelize
|
3
|
+
self.split("_").each {|s| s.capitalize! }.join("")
|
4
|
+
end
|
5
|
+
|
6
|
+
def snakecase
|
7
|
+
#gsub(/::/, '/').
|
8
|
+
gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
|
9
|
+
gsub(/([a-z\d])([A-Z])/,'\1_\2').
|
10
|
+
tr('-', '_').
|
11
|
+
gsub(/\s/, '_').
|
12
|
+
gsub(/__+/, '_').
|
13
|
+
downcase
|
14
|
+
end
|
15
|
+
|
16
|
+
def constantize
|
17
|
+
names = self.split('::')
|
18
|
+
names.shift if names.empty? || names.first.empty?
|
19
|
+
names.inject(Object) do |constant, name|
|
20
|
+
if constant == Object
|
21
|
+
constant.const_get(name)
|
22
|
+
else
|
23
|
+
candidate = constant.const_get(name)
|
24
|
+
next candidate if constant.const_defined?(name, false)
|
25
|
+
next candidate unless Object.const_defined?(name)
|
26
|
+
# Go down the ancestors to check it it's owned
|
27
|
+
# directly before we reach Object or the end of ancestors.
|
28
|
+
constant = constant.ancestors.inject do |const, ancestor|
|
29
|
+
break const if ancestor == Object
|
30
|
+
break ancestor if ancestor.const_defined?(name, false)
|
31
|
+
const
|
32
|
+
end
|
33
|
+
# owner is in Object, so raise
|
34
|
+
constant.const_get(name, false)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
data/lib/verilog_gen/version.rb
CHANGED
@@ -0,0 +1,38 @@
|
|
1
|
+
// --------------------------------------------------
|
2
|
+
//
|
3
|
+
// Generic memory
|
4
|
+
//
|
5
|
+
// This module is a generic memory with write/read enables and
|
6
|
+
// read data is available registered (next clock cycle). The
|
7
|
+
// Width and Depth of the memory are parameterizeable.
|
8
|
+
//
|
9
|
+
// --------------------------------------------------
|
10
|
+
|
11
|
+
module generic_mem
|
12
|
+
#( parameter DEPTH=8,
|
13
|
+
parameter WIDTH=32,
|
14
|
+
localparam AWIDTH=$clog2(DEPTH) )
|
15
|
+
(
|
16
|
+
input wire clk,
|
17
|
+
input wire mem_wr_en,
|
18
|
+
input wire [AWIDTH-1:0] mem_wr_addr,
|
19
|
+
input wire [WIDTH-1:0] mem_wr_data,
|
20
|
+
input wire mem_rd_en,
|
21
|
+
input wire [AWIDTH-1:0] mem_rd_addr,
|
22
|
+
input wire [WIDTH-1:0] mem_rd_data
|
23
|
+
);
|
24
|
+
|
25
|
+
// The memory declaration
|
26
|
+
reg [WIDTH-1:0] generic_memory [DEPTH-1:0];
|
27
|
+
|
28
|
+
always @ (posedge clk) begin
|
29
|
+
if( mem_wr_en ) begin
|
30
|
+
generic_memory[mem_wr_addr] <= #0 mem_wr_data;
|
31
|
+
end
|
32
|
+
|
33
|
+
if( mem_rd_en ) begin
|
34
|
+
mem_rd_data <= #0 generic_memory[mem_rd_addr];
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
endmodule
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
# Check the syntax for accessing child instances in array.
|
4
|
+
#
|
5
|
+
describe VerilogGen::HdlModule do
|
6
|
+
before(:all) do
|
7
|
+
class Leaf < VerilogGen::HdlModule
|
8
|
+
end
|
9
|
+
|
10
|
+
class Node < VerilogGen::HdlModule;
|
11
|
+
10.times do |i|
|
12
|
+
add_child_instance "leaf#{i}", Leaf
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
it "should have the correct number of chilren" do
|
18
|
+
expect(Node.child_instances.size).to eq(10)
|
19
|
+
end
|
20
|
+
it "should support dot notation" do
|
21
|
+
expect(Node.leaf0.instance_name).to eq("leaf0")
|
22
|
+
end
|
23
|
+
it "should support loop in dot notation" do
|
24
|
+
10.times do |i|
|
25
|
+
expect(Node.child_instances["leaf#{i}"].instance_name).to eq("leaf#{i}")
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|