HDLRuby 2.10.2 → 2.10.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +242 -235
- data/lib/HDLRuby/version.rb +1 -1
- metadata +2 -2
data/README.md
CHANGED
@@ -11,7 +11,7 @@ The recommended installation method is from rubygem as follows:
|
|
11
11
|
gem install HDLRuby
|
12
12
|
```
|
13
13
|
|
14
|
-
Developers willing to contribute to HDLRuby can install the sources from
|
14
|
+
Developers willing to contribute to HDLRuby can install the sources from GitHub as follows:
|
15
15
|
|
16
16
|
```
|
17
17
|
git clone HDLRuby
|
@@ -19,15 +19,15 @@ git clone HDLRuby
|
|
19
19
|
|
20
20
|
__Warning__:
|
21
21
|
|
22
|
-
- This is still preliminary work which may change
|
23
|
-
- It is highly recommended to have both basic
|
22
|
+
- This is still preliminary work which may change before we release a stable version.
|
23
|
+
- It is highly recommended to have both basic knowledges of the Ruby language and hardware description languages before using HDLRuby.
|
24
24
|
|
25
25
|
|
26
26
|
# Compiling HDLRuby descriptions
|
27
27
|
|
28
28
|
## Using the HDLRuby compiler
|
29
29
|
|
30
|
-
'hdrcc' is the HDLRuby compiler. It takes as input
|
30
|
+
'hdrcc' is the HDLRuby compiler. It takes as input an HDLRuby file, checks it, and can produce as output a Verilog HDL, VHDL, or a YAML low-level descriptions of HW components but it can also simulate the input description.
|
31
31
|
|
32
32
|
|
33
33
|
__Usage__:
|
@@ -51,7 +51,7 @@ Where:
|
|
51
51
|
| `-s, --syntax` | Output the Ruby syntax tree |
|
52
52
|
| `-C, --clang` | Output the C code of the simulator |
|
53
53
|
| `-S, --sim` | Output the executable simulator and execute it |
|
54
|
-
| `--vcd` | Make the simulator generate a
|
54
|
+
| `--vcd` | Make the simulator generate a VCD file |
|
55
55
|
| `-d, --directory` | Specify the base directory for loading the HDLRuby files |
|
56
56
|
| `-D, --debug` | Set the HDLRuby debug mode |
|
57
57
|
| `-t, --top system`| Specify the top system describing the circuit to compile |
|
@@ -62,7 +62,7 @@ Where:
|
|
62
62
|
__Notes__:
|
63
63
|
|
64
64
|
* If no top system is given, it is automatically looked for from the input file.
|
65
|
-
* If no option is given, simply checks the input file.
|
65
|
+
* If no option is given, it simply checks the input file.
|
66
66
|
* The simulator option (-S) requires a standard compiler (accessible through the command `cc`) to be available in the executable path.
|
67
67
|
|
68
68
|
__Examples__:
|
@@ -110,68 +110,46 @@ hdrcc -I
|
|
110
110
|
hdrcc -I pry
|
111
111
|
```
|
112
112
|
|
113
|
+
## Using HDLRuby in interactive mode
|
113
114
|
|
114
|
-
|
115
|
+
When running in interactive mode, the HDLRuby framework starts a REPL prompt and creates a working directory called 'HDLRubyWorkspace'. By default, the REPL is 'irb', but it can be set to 'pry'. Within this prompt, HDLRuby code can be written like in an HDLRuby description file. However, to process this code the following commands are added:
|
115
116
|
|
116
|
-
|
117
|
+
* Compile an HDLRuby module:
|
117
118
|
|
118
119
|
```ruby
|
119
|
-
|
120
|
+
hdr_make(<module>)
|
120
121
|
```
|
121
122
|
|
122
|
-
|
123
|
+
* Generate and display the IR of the compiled module in YAML form:
|
123
124
|
|
124
125
|
```ruby
|
125
|
-
|
126
|
+
hdr_yaml
|
126
127
|
```
|
127
128
|
|
128
|
-
|
129
|
-
from an instance of an HW module (*system* in HDLRuby).
|
130
|
-
For example, assuming system 'circuitT' has been described in your Ruby program, an instance named 'circuitI' can be declared as follows:
|
129
|
+
* Regenerate and display the HDLRuby description of the compiled module:
|
131
130
|
|
132
131
|
```ruby
|
133
|
-
|
132
|
+
hdr_hdr
|
134
133
|
```
|
135
134
|
|
136
|
-
|
135
|
+
* Generate and output in the working directory the Verilog HDL RTL of the compiled module:
|
137
136
|
|
138
137
|
```ruby
|
139
|
-
|
138
|
+
hdr_verilog
|
140
139
|
```
|
141
140
|
|
142
|
-
|
141
|
+
* Generate and output in the working directory the Verilog HDL RTL of the compiled module:
|
143
142
|
|
144
143
|
```ruby
|
145
|
-
|
146
|
-
circuitV = circuitL.to_vhdl
|
144
|
+
hdr_vhdl
|
147
145
|
```
|
148
146
|
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
## Handling the low-level HDLRuby representation
|
153
|
-
|
154
|
-
You can include `HDLRuby::Low` for gaining access to the classes used for low-level description of hardware components.
|
147
|
+
* Simulate the compiled module:
|
155
148
|
|
156
149
|
```ruby
|
157
|
-
|
150
|
+
hdr_sim
|
158
151
|
```
|
159
152
|
|
160
|
-
It is then possible to load a low-level representation of hardware as follows, where `stream` is a stream containing the representation.
|
161
|
-
|
162
|
-
```ruby
|
163
|
-
hardwares = HDLRuby::from_yaml(stream)
|
164
|
-
```
|
165
|
-
|
166
|
-
For instance, you can load the sample description of an 8-bit adder as follows:
|
167
|
-
|
168
|
-
```ruby
|
169
|
-
adder = HDLRuby::from_yaml(File.read("#{$:[0]}/HDLRuby/low_samples/adder.yaml"))
|
170
|
-
```
|
171
|
-
|
172
|
-
__Note__:
|
173
|
-
|
174
|
-
- A `HDLRuby::Low` description of hardware can only be built through standard Ruby class constructors and does not include any validity check of the resulting hardware.
|
175
153
|
|
176
154
|
|
177
155
|
|
@@ -184,7 +162,7 @@ The second specificity of HDLRuby is that it supports natively all the features
|
|
184
162
|
|
185
163
|
__Notes__:
|
186
164
|
|
187
|
-
- It is still possible to extend HDLRuby to support hardware descriptions of higher level than RTL, please refer to section [Extending HDLRuby](#extend) for more details.
|
165
|
+
- It is still possible to extend HDLRuby to support hardware descriptions of a higher level than RTL, please refer to section [Extending HDLRuby](#extend) for more details.
|
188
166
|
- In this document, HDLRuby constructs will often be compared to their Verilog HDL or VHDL equivalents for simpler explanations.
|
189
167
|
|
190
168
|
## Introduction
|
@@ -192,7 +170,7 @@ __Notes__:
|
|
192
170
|
This introduction gives a glimpse of the possibilities of the language.
|
193
171
|
However, we do recommend consulting the section about the [high-level programming features](#highfeat) to have a more complete view of the advanced possibilities of this language.
|
194
172
|
|
195
|
-
At first glance, HDLRuby appears like any other HDL
|
173
|
+
At first glance, HDLRuby appears like any other HDL (like Verilog HDL or VHDL), for instance, the following code describes a simple D-FF:
|
196
174
|
|
197
175
|
```ruby
|
198
176
|
system :dff do
|
@@ -251,11 +229,11 @@ end
|
|
251
229
|
In the code above, two possible connection methods are shown: for `dff0` ports are connected by name, and for `dff1` ports are connected by declaration order. Please notice that it is also possible to connect only a subset of the ports while declaring and to reconnect already connected ports in further statements.
|
252
230
|
|
253
231
|
While a circuit can be generated from the code given above, a benchmark must
|
254
|
-
be provided to test it. Such benchmark
|
255
|
-
timed behavior that give the evolution of signals depending
|
232
|
+
be provided to test it. Such a benchmark is described by constructs called
|
233
|
+
timed behavior that give the evolution of signals depending on the time.
|
256
234
|
For example, the following code simulates the previous D-FF for 4 cycles
|
257
|
-
of 20ns each, with reset on the first cycle, set of signal `d` to 1 for
|
258
|
-
the third cycle and set
|
235
|
+
of 20ns each, with a reset on the first cycle, set of signal `d` to 1 for
|
236
|
+
the third cycle and set this signal to 0 for the last.
|
259
237
|
|
260
238
|
```ruby
|
261
239
|
system :dff_bench do
|
@@ -289,9 +267,9 @@ end
|
|
289
267
|
|
290
268
|
---
|
291
269
|
|
292
|
-
The code describing a `dff` given above is not much different from its equivalent in any other HDL. However, HDLRuby provides several features for achieving
|
270
|
+
The code describing a `dff` given above is not much different from its equivalent in any other HDL. However, HDLRuby provides several features for achieving higher productivity when describing hardware. We will now describe a few of them.
|
293
271
|
|
294
|
-
First, several syntactic sugars exist that allow shorter code, for instance the following code is strictly equivalent to the previous description of `dff`:
|
272
|
+
First, several syntactic sugars exist that allow shorter code, for instance, the following code is strictly equivalent to the previous description of `dff`:
|
295
273
|
|
296
274
|
```ruby
|
297
275
|
system :dff do
|
@@ -355,7 +333,7 @@ system :reg do |typ|
|
|
355
333
|
end
|
356
334
|
```
|
357
335
|
|
358
|
-
Wait... I have just realized
|
336
|
+
Wait... I have just realized that D-FF without any inverted output does not look very serious. So, let us extend the existing `dff` to provide an inverted output. There are three ways for doing this. First, inheritance can be used: a new system is built inheriting from `dff` as it is done in the following code.
|
359
337
|
|
360
338
|
```ruby
|
361
339
|
system :dff_full, dff do
|
@@ -364,7 +342,7 @@ system :dff_full, dff do
|
|
364
342
|
end
|
365
343
|
```
|
366
344
|
|
367
|
-
The second possibility is to modify `dff` afterward. In HDLRuby, this achieved using the `open` method as it is done the following code:
|
345
|
+
The second possibility is to modify `dff` afterward. In HDLRuby, this is achieved using the `open` method as it is done in the following code:
|
368
346
|
|
369
347
|
```ruby
|
370
348
|
dff.open do
|
@@ -373,7 +351,7 @@ dff.open do
|
|
373
351
|
end
|
374
352
|
```
|
375
353
|
|
376
|
-
The third possibility is to modify directly a single instance of `dff` which
|
354
|
+
The third possibility is to modify directly a single instance of `dff` which requires an inverted output, using again the `open` method, as in the following code:
|
377
355
|
|
378
356
|
```ruby
|
379
357
|
# Declare dff0 as an instance of dff
|
@@ -386,10 +364,10 @@ dff0.open do
|
|
386
364
|
end
|
387
365
|
```
|
388
366
|
|
389
|
-
In this
|
367
|
+
In this latter case, only `dff0` will have an inverted output, the other instances of `dff` will not change.
|
390
368
|
|
391
|
-
Now assuming we opted for the first solution, we have now `dff_full`, a highly advanced D-FF with such unique features as an inverted output. So, we would like to use it in other designs, for example a shift register of `n` bits. Such a system will include a generic number of `dff_full` instances
|
392
|
-
described as follows making use of the native Ruby method `each_cons` for connecting them
|
369
|
+
Now assuming we opted for the first solution, we have now `dff_full`, a highly advanced D-FF with such unique features as an inverted output. So, we would like to use it in other designs, for example, a shift register of `n` bits. Such a system will include a generic number of `dff_full` instances and can be
|
370
|
+
described as follows making use of the native Ruby method `each_cons` for connecting them:
|
393
371
|
|
394
372
|
```ruby
|
395
373
|
system :shifter do |n|
|
@@ -413,7 +391,7 @@ system :shifter do |n|
|
|
413
391
|
end
|
414
392
|
```
|
415
393
|
|
416
|
-
As it can be seen in the above examples, in HDLRuby, any construct is an object and therefore include methods. For instance, declaring a signal of a given `type` and direction (input, output or inout) is done as follows
|
394
|
+
As it can be seen in the above examples, in HDLRuby, any construct is an object and therefore include methods. For instance, declaring a signal of a given `type` and direction (input, output, or inout) is done as follows so that `direction` is a method of the type, and the signal names are the arguments of this method (symbols or string are supported.)
|
417
395
|
|
418
396
|
```ruby
|
419
397
|
<type>.<direction> <list of symbols representing the signal>
|
@@ -437,7 +415,7 @@ system :shifter do |n|
|
|
437
415
|
end
|
438
416
|
```
|
439
417
|
|
440
|
-
Now, let us assume you want to design a circuit that performs a sum of products of several inputs with constant coefficients. For the case of 4 16-bit signed inputs and given
|
418
|
+
Now, let us assume you want to design a circuit that performs a sum of products of several inputs with constant coefficients. For the case of 4 16-bit signed inputs and given coefficients as 3, 4, 5, and 6. The corresponding basic code could be as follows:
|
441
419
|
|
442
420
|
```ruby
|
443
421
|
system :sumprod_16_3456 do
|
@@ -448,7 +426,7 @@ system :sumprod_16_3456 do
|
|
448
426
|
end
|
449
427
|
```
|
450
428
|
|
451
|
-
The description above is
|
429
|
+
The description above is straightforward, but it would be necessary to rewrite it if another circuit with different bit width or coefficients is to be designed. Moreover, if the number of coefficients is large an error in the expression will be easy to make and hard to find. A better approach would be to use a generic description of such a circuit as follows:
|
452
430
|
|
453
431
|
```ruby
|
454
432
|
system :sumprod do |typ,coefs|
|
@@ -462,19 +440,19 @@ end
|
|
462
440
|
```
|
463
441
|
|
464
442
|
In the code above, there are two generic parameters,
|
465
|
-
`typ
|
443
|
+
`typ`, which indicates the data type of the circuit, and `coefs`, which is assumed to be an array of coefficients. Since the number of inputs depends on the number of provided coefficients, it is declared as an array of `width` bit signed whose size is equal to the number of coefficients.
|
466
444
|
|
467
|
-
The description of the sum of
|
445
|
+
The description of the sum of products may be more difficult to understand for people not familiar with the Ruby language. The `each_with_index` method iterates over the coefficients adding their index as iteration variable, the resulting operation (i.e., the iteration loop) is then modified by the `reduce` method that accumulates the code passed as arguments. This code, starting by `|sum,coef,i|` simply performs the addition of the current accumulation result (`sum`) with the product of the current coefficient (`coef`) and input (`ins[i]`, where `i` is the index) in the iteration. The argument `_0` initializes the sum to `0`.
|
468
446
|
|
469
|
-
While slightly longer than the previous description, this description allows
|
447
|
+
While slightly longer than the previous description, this description allows declaring a circuit implementing a sum of products with any bit width and any number of coefficients. For instance, the following code describes a signed 32-bit sum of products with 16 coefficients (just random numbers here).
|
470
448
|
|
471
449
|
```ruby
|
472
450
|
sumprod(signed[32], [3,78,43,246, 3,67,1,8, 47,82,99,13, 5,77,2,4]).(:my_circuit)
|
473
451
|
```
|
474
452
|
|
475
|
-
As seen in the code above, when passing generic argument for instantiating a generic system, the name of the instance is put between brackets for avoiding confusion.
|
453
|
+
As seen in the code above, when passing a generic argument for instantiating a generic system, the name of the instance is put between brackets for avoiding confusion.
|
476
454
|
|
477
|
-
While description `sumprod` is already usable in a wide range of cases, it still uses the standard addition and multiplication. However, there are cases where specific components are to be used for these operations, either for sake of performance, compliance with constraints, or because functionally different operations are required (e.g., saturated computations). This can be solved by using functions implementing such computation in place of operators, for example as follows:
|
455
|
+
While the description `sumprod` is already usable in a wide range of cases, it still uses the standard addition and multiplication. However, there are cases where specific components are to be used for these operations, either for sake of performance, compliance with constraints, or because functionally different operations are required (e.g., saturated computations). This can be solved by using functions implementing such computation in place of operators, for example as follows:
|
478
456
|
|
479
457
|
```ruby
|
480
458
|
system :sumprod_func do |typ,coefs|
|
@@ -500,13 +478,13 @@ function :add do |x,y|
|
|
500
478
|
end
|
501
479
|
```
|
502
480
|
|
503
|
-
With HDLRuby functions, the result of the last statement in the return value, in this case that will be the value of res. The code above is also an example of the usage of the postfixed if statement, it an equivalent of the following code:
|
481
|
+
With HDLRuby functions, the result of the last statement in the return value, in this case, that will be the value of res. The code above is also an example of the usage of the postfixed if statement, it is an equivalent of the following code:
|
504
482
|
|
505
483
|
```ruby
|
506
484
|
hif(res>1000) { res <= 1000 }
|
507
485
|
```
|
508
486
|
|
509
|
-
With functions, it is enough to change their content to obtain a new kind of circuit without
|
487
|
+
With functions, it is enough to change their content to obtain a new kind of circuit without changing the main code. This approach suffers from two drawbacks though: first, the level of saturation is hard coded in the function, and second, it would be preferable to be able to select the function to execute instead of modifying its code. For the first problem, a simple approach is to add an argument to the function given the saturation level. Such an add function would therefore be as follows:
|
510
488
|
|
511
489
|
```ruby
|
512
490
|
function :add do |max, x, y|
|
@@ -518,9 +496,9 @@ function :add do |max, x, y|
|
|
518
496
|
end
|
519
497
|
```
|
520
498
|
|
521
|
-
It would however be necessary to add this argument when invoking the function, e.g., `add(1000,sum,mult(...))`. While this argument is relevant for addition with saturation, it is not for the other kind of addition operations, and hence, the code of `sumprod` is not general any longer.
|
499
|
+
It would however be necessary to add this argument when invoking the function, e.g., `add(1000,sum,mult(...))`. While this argument is relevant for addition with saturation, it is not for the other kind of addition operations, and hence, the code of `sumprod` is not general-purpose any longer.
|
522
500
|
|
523
|
-
HDLRuby provides two ways to address such issues. First, it is possible to pass code as argument. In the case of `sumprod` it would then be enough to add two arguments that perform the required addition and multiplication. The example is below:
|
501
|
+
HDLRuby provides two ways to address such issues. First, it is possible to pass code as an argument. In the case of `sumprod` it would then be enough to add two arguments that perform the required addition and multiplication. The example is below:
|
524
502
|
|
525
503
|
```ruby
|
526
504
|
system :sumprod_proc do |add,mult,typ,coefs|
|
@@ -536,7 +514,7 @@ end
|
|
536
514
|
|
537
515
|
__Note__:
|
538
516
|
|
539
|
-
- With HDLRuby, when some code is passed as argument, it is invoked using the `.()` operator, and not simple parenthesis
|
517
|
+
- With HDLRuby, when some code is passed as an argument, it is invoked using the `.()` operator, and not simple parenthesis-like functions.
|
540
518
|
|
541
519
|
Assuming the addition with saturation is now implemented by a function named `add_sat` and a multiplication with saturation is implemented by a function named `mult_sat` (with similar arguments), a circuit implementing a signed 16-bit sum of product saturating at 1000 with 16 coefficients could be described as follows:
|
542
520
|
|
@@ -549,7 +527,7 @@ sumprod_proc(
|
|
549
527
|
47,82,99,13, 5,77,2,4]).(:my_circuit)
|
550
528
|
```
|
551
529
|
|
552
|
-
As seen in the example above, a piece of code is passed as argument using the proc keyword.
|
530
|
+
As seen in the example above, a piece of code is passed as an argument using the proc keyword.
|
553
531
|
|
554
532
|
A second possible approach provided by HDLRuby is to declare a new data type with redefined addition and multiplication operators. For the case of a 16-bit saturated addition and multiplication the following generic data type can be defined (for signed computations):
|
555
533
|
|
@@ -604,7 +582,7 @@ sumprod(sat(16,1000),
|
|
604
582
|
```
|
605
583
|
|
606
584
|
|
607
|
-
|
585
|
+
Lastly note, HDLRuby is also a language with supports reflection for
|
608
586
|
all its constructs. For example, the system of an instance can be accessed
|
609
587
|
using the `systemT` method, and this latter can be used to create
|
610
588
|
other instances. For example, previously, `dff_single` was declared with
|
@@ -621,28 +599,28 @@ of the same system as `dff_single`.
|
|
621
599
|
This reflection capability can also be used for instance, for accessing the
|
622
600
|
data type of a signal (`sig.type`), but also the current basic block
|
623
601
|
(`cur_block`), the current process (`cur_behavior`) and so on.
|
624
|
-
The standard library of HDLRuby
|
625
|
-
like finite state machine descriptors
|
602
|
+
The standard library of HDLRuby includes several hardware constructs
|
603
|
+
like finite state machine descriptors and is mainly based on using these
|
626
604
|
reflection features.
|
627
605
|
|
628
606
|
|
629
607
|
|
630
608
|
## How does HDLRuby work
|
631
609
|
|
632
|
-
Contrary to descriptions in high-level HDL like SystemVerilog, VHDL or SystemC, HDLRuby descriptions are not software-like
|
610
|
+
Contrary to descriptions in high-level HDL like SystemVerilog, VHDL, or SystemC, HDLRuby descriptions are not software-like descriptions of hardware but are programs meant to produce hardware descriptions. In other words, while the execution of a common HDL code will result in some simulation of the described hardware, the execution of HDLRuby code will result in some low-level hardware description. This low-level description is synthesizable and can also be simulated like any standard hardware description.
|
633
611
|
This decoupling of the representation of the hardware from the point of view of the user (HDLRuby), and the actual hardware description (HDLRuby::Low) makes it possible to provide the user with any advanced software features without jeopardizing the synthesizability of the actual hardware description.
|
634
612
|
|
635
|
-
For that purpose, each construct in HDLRuby is not a direct description of some hardware construct, but a program
|
613
|
+
For that purpose, each construct in HDLRuby is not a direct description of some hardware construct, but a program that generates the corresponding description. For example, let us consider the following line of code of HDLRuby describing the connection between signal `a` and signal `b`:
|
636
614
|
|
637
615
|
```ruby
|
638
616
|
a <= b
|
639
617
|
```
|
640
618
|
|
641
|
-
Its execution will produce the actual hardware description of this connection as an object of the HDLRuby::Low library — in this case an instance of the `HDLRuby::Low::Connection` class. Concretely,
|
619
|
+
Its execution will produce the actual hardware description of this connection as an object of the HDLRuby::Low library — in this case, an instance of the `HDLRuby::Low::Connection` class. Concretely, an HDLRuby system is described by a Ruby block, and the instantiation of this system is performed by executing this block. The actual synthesizable description of this hardware is the execution result of this instantiation.
|
642
620
|
|
643
621
|
|
644
622
|
|
645
|
-
From there, we will describe
|
623
|
+
From there, we will describe in more detail each construct of HDLRuby.
|
646
624
|
|
647
625
|
## Naming rules
|
648
626
|
<a name="names"></a>
|
@@ -650,17 +628,17 @@ From there, we will describe into more details each construct of HDLRuby.
|
|
650
628
|
Several constructs in HDLRuby are referred to by name, e.g., systems and signals. When such constructs are declared, their names are to be specified by Ruby symbols starting with a lower case. For example, `:hello` is a valid name declaration, but `:Hello` is not.
|
651
629
|
|
652
630
|
After being declared, the construct can be referred to by using the name directly (i.e., without the `:` of Ruby symbols). For example, if a construct
|
653
|
-
has been declared with `:hello` as name, it will be afterward referred by `hello`.
|
631
|
+
has been declared with `:hello` as name, it will be afterward referred to by `hello`.
|
654
632
|
|
655
633
|
## Systems and signals
|
656
634
|
|
657
|
-
A system represents a digital system and corresponds to a Verilog HDL module. A system has an interface comprising input, output, and inout signals, and includes
|
635
|
+
A system represents a digital system and corresponds to a Verilog HDL module. A system has an interface comprising input, output, and inout signals, and includes structural and behavioral descriptions.
|
658
636
|
|
659
|
-
A signal represents a state in a system. It has a data type and a value, the latter varying with time. HDLRuby signals can be viewed as abstractions of both wires and registers in a digital circuit. As general rule, a signal whose value is explicitly set all the time models a wire, otherwise it models a register.
|
637
|
+
A signal represents a state in a system. It has a data type and a value, the latter varying with time. HDLRuby signals can be viewed as abstractions of both wires and registers in a digital circuit. As a general rule, a signal whose value is explicitly set all the time models a wire, otherwise it models a register.
|
660
638
|
|
661
639
|
### Declaring an empty system
|
662
640
|
|
663
|
-
A system is declared using the keyword `system`. It must be given a Ruby symbol for name and a block that describe its content. For instance, the following code describes an empty system named `box`:
|
641
|
+
A system is declared using the keyword `system`. It must be given a Ruby symbol for its name and a block that describe its content. For instance, the following code describes an empty system named `box`:
|
664
642
|
|
665
643
|
```ruby
|
666
644
|
system(:box) {}
|
@@ -669,7 +647,7 @@ system(:box) {}
|
|
669
647
|
__Notes__:
|
670
648
|
|
671
649
|
- Since this is Ruby code, the body can also be delimited by the `do` and `end`
|
672
|
-
Ruby keywords (in which case the parentheses can be omitted) as follows:
|
650
|
+
Ruby keywords (in which case the parentheses can be omitted) are as follows:
|
673
651
|
|
674
652
|
```ruby
|
675
653
|
system :box do
|
@@ -681,7 +659,7 @@ end
|
|
681
659
|
|
682
660
|
### Declaring a system with an interface
|
683
661
|
|
684
|
-
The interface of a system can be described anywhere in its body, but it is recommended to do it at its beginning. This is done by declaring input, output or inout signals of given data types as follows:
|
662
|
+
The interface of a system can be described anywhere in its body, but it is recommended to do it at its beginning. This is done by declaring input, output, or inout signals of given data types as follows:
|
685
663
|
|
686
664
|
```ruby
|
687
665
|
<data type>.<direction> <list of colon-preceded names>
|
@@ -700,7 +678,7 @@ input :clk
|
|
700
678
|
```
|
701
679
|
|
702
680
|
The following is a more complete example: it is the code of a system describing an 8-bit data, 16-bit address memory whose interface includes a 1-bit input
|
703
|
-
clock (`clk`), a 1-bit signal for selecting reading or writing access (`rwb`), a 16-bit address input (`addr`) and an 8-bit data inout — the remaining of the code describes the content and the behavior of the memory.
|
681
|
+
clock (`clk`), a 1-bit signal for selecting reading or writing access (`rwb`), a 16-bit address input (`addr`), and an 8-bit data inout — the remaining of the code describes the content and the behavior of the memory.
|
704
682
|
|
705
683
|
```ruby
|
706
684
|
system :mem8_16 do
|
@@ -733,7 +711,7 @@ For example, system `mem8_16` declared in the previous section can be instantiat
|
|
733
711
|
mem8_16 :mem8_16I
|
734
712
|
```
|
735
713
|
|
736
|
-
It is also possible to declare multiple instances of
|
714
|
+
It is also possible to declare multiple instances of the same system at a time as follows:
|
737
715
|
|
738
716
|
```ruby
|
739
717
|
<system name> [list of colon-separated instance names]
|
@@ -754,7 +732,7 @@ inner :w1
|
|
754
732
|
[1..0].inner :w2
|
755
733
|
```
|
756
734
|
|
757
|
-
If the signal is not meant to be changed,
|
735
|
+
If the signal is not meant to be changed, it can be declared using the `constant` keyword instead of `inner`.
|
758
736
|
|
759
737
|
A connection between signals is done using the arrow operator `<=` as follows:
|
760
738
|
|
@@ -777,7 +755,7 @@ As another example, the following code connects to the second bit of `w2` the ou
|
|
777
755
|
w2[1] <= clk & rst
|
778
756
|
```
|
779
757
|
|
780
|
-
The signals of an instance can be connected through the arrow operator too, provided they are properly referred to. One way to refer them is to use the dot operator `.` on the instance as follows:
|
758
|
+
The signals of an instance can be connected through the arrow operator too, provided they are properly referred to. One way to refer to them is to use the dot operator `.` on the instance as follows:
|
781
759
|
|
782
760
|
```ruby
|
783
761
|
<instance name>.<signal name>
|
@@ -847,19 +825,19 @@ end
|
|
847
825
|
### Initialization of signals
|
848
826
|
<a name="initialization"></a>
|
849
827
|
|
850
|
-
Output, inner and constant signals of a system can be
|
828
|
+
Output, inner and constant signals of a system can be initialized when declared using the following syntax in place of the usual name of the signal:
|
851
829
|
|
852
830
|
```ruby
|
853
831
|
<signal name>: <intial value>
|
854
832
|
```
|
855
833
|
|
856
|
-
For example a single
|
834
|
+
For example, a single-bit inner signal named `sig` can be initialized to 0 as follows:
|
857
835
|
|
858
836
|
```ruby
|
859
837
|
inner sig: 0
|
860
838
|
```
|
861
839
|
|
862
|
-
As
|
840
|
+
As another example, an 8-bit 8-word ROM could be declared and initialized as follows:
|
863
841
|
|
864
842
|
```ruby
|
865
843
|
bit[8][-8] rom: [ 0,1,2,3,4,5,6,7 ]
|
@@ -870,9 +848,9 @@ bit[8][-8] rom: [ 0,1,2,3,4,5,6,7 ]
|
|
870
848
|
|
871
849
|
#### General scopes
|
872
850
|
|
873
|
-
The signals of the interface of signals are accessible from anywhere in
|
851
|
+
The signals of the interface of signals are accessible from anywhere in an HDLRuby description. This is not the case for inner signals and instances: they are accessible only within the scope they are declared in.
|
874
852
|
|
875
|
-
A scope is a region of the code where locally declared objects are accessible. Each system has its
|
853
|
+
A scope is a region of the code where locally declared objects are accessible. Each system has its scope that cannot be accessible from another part of an HDLRuby description. For example, in the following code signals `d` and `qb` as well as instance `dffI` cannot be accessed from outside system `div2`:
|
876
854
|
|
877
855
|
```ruby
|
878
856
|
system :div2 do
|
@@ -886,7 +864,7 @@ system :div2 do
|
|
886
864
|
|
887
865
|
```
|
888
866
|
|
889
|
-
For robustness or, readability purpose, it is possible to add inner scope inside existing scope using the `sub` keyword as follows:
|
867
|
+
For robustness or, readability purpose, it is possible to add inner scope inside the existing scope using the `sub` keyword as follows:
|
890
868
|
|
891
869
|
```ruby
|
892
870
|
sub do
|
@@ -894,7 +872,7 @@ sub do
|
|
894
872
|
end
|
895
873
|
```
|
896
874
|
|
897
|
-
For example, in the code
|
875
|
+
For example, in the code below signal `sig` is not accessible from outside the additional inner scope of system `sys`
|
898
876
|
|
899
877
|
```ruby
|
900
878
|
system :sys do
|
@@ -925,7 +903,7 @@ system :sys do
|
|
925
903
|
end
|
926
904
|
```
|
927
905
|
|
928
|
-
Within
|
906
|
+
Within the same scope, it is not possible to declare multiple signals or instances with the same name. However, it is possible to declare a signal or an instance with a name identical to one previously declared outside the scope: the inner-most declaration will be used.
|
929
907
|
|
930
908
|
|
931
909
|
#### Named scopes
|
@@ -943,7 +921,7 @@ Where:
|
|
943
921
|
* `<name>` is the name of the scope.
|
944
922
|
* `<code>` is the code within the scope.
|
945
923
|
|
946
|
-
Contrary to the case of scopes without name, signals and instances declared within a named scope can be accessed outside using this name as reference. For example, in the code
|
924
|
+
Contrary to the case of scopes without a name, signals and instances declared within a named scope can be accessed outside using this name as a reference. For example, in the code below signal `sig` declared within scope named `scop` is accessed outside it using `scop.sig`:
|
947
925
|
|
948
926
|
```ruby
|
949
927
|
sub :scop do
|
@@ -971,11 +949,11 @@ In addition, it is possible to declare inner signals within an execution block.
|
|
971
949
|
While such signals will be physically linked to the system, they are only accessible within the block they are declared into. This permits a tighter scope for signals, which improves the readability of the code and make it possible to declare several signals with identical names provided their respective scopes are different.
|
972
950
|
|
973
951
|
An event represents a specific change of state of a signal.
|
974
|
-
For example, a rising edge of a clock signal named `clk` will be represented by event `clk.posedge`. In HDLRuby, events are obtained directly from
|
975
|
-
expressions using the following methods: `posedge` for rising edge, `negedge` for falling edge, and `edge` for any edge.
|
952
|
+
For example, a rising edge of a clock signal named `clk` will be represented by the event `clk.posedge`. In HDLRuby, events are obtained directly from
|
953
|
+
expressions using the following methods: `posedge` for a rising edge, `negedge` for a falling edge, and `edge` for any edge.
|
976
954
|
Events are described in more detail in section [Events](#events).
|
977
955
|
|
978
|
-
When one of the events of the sensitivity list of a behavior occurs, the behavior is executed, i.e., each of its statements is executed in sequence. A statement can represent a data transmission to a signal, a control flow, a nested execution block or the declaration of an inner signal (as stated
|
956
|
+
When one of the events of the sensitivity list of a behavior occurs, the behavior is executed, i.e., each of its statements is executed in sequence. A statement can represent a data transmission to a signal, a control flow, a nested execution block, or the declaration of an inner signal (as stated
|
979
957
|
earlier). Statements are described in more detail in section [statements](#statements). In this section, we focus on the transmission statements and the block statements.
|
980
958
|
|
981
959
|
A transmission statement is declared using the arrow operator `<=` as follows:
|
@@ -986,8 +964,8 @@ A transmission statement is declared using the arrow operator `<=` as follows:
|
|
986
964
|
|
987
965
|
The `<destination>` must be a reference to a signal, and the `<source>` can be any expression. A transmission has therefore the same structure as a connection. However, its execution model is different: whereas a connection is continuously executed, a transmission is only executed during the execution of its block.
|
988
966
|
|
989
|
-
A block comprises a list of statements. It is used for adding hierarchy
|
990
|
-
By default, a top block is created when declaring a behavior, and it inherits from its execution mode. For example, with the following code the top block of the behavior is sequential.
|
967
|
+
A block comprises a list of statements. It is used for adding hierarchy to a behavior. Blocks can be either parallel or sequential, i.e., their transmission statements are respectively non-blocking or blocking.
|
968
|
+
By default, a top block is created when declaring a behavior, and it inherits from its execution mode. For example, with the following code, the top block of the behavior is sequential.
|
991
969
|
|
992
970
|
```ruby
|
993
971
|
system :with_sequential_behavior do
|
@@ -998,7 +976,7 @@ end
|
|
998
976
|
```
|
999
977
|
|
1000
978
|
It is possible to declare new blocks within an existing block.
|
1001
|
-
For declaring a sub
|
979
|
+
For declaring a sub-block with the same execution mode as the upper one, the keyword `sub` is used. For example, the following code declares a sub-block within a sequential block, with the same execution mode:
|
1002
980
|
|
1003
981
|
```ruby
|
1004
982
|
system :with_sequential_behavior do
|
@@ -1011,7 +989,7 @@ system :with_sequential_behavior do
|
|
1011
989
|
end
|
1012
990
|
```
|
1013
991
|
|
1014
|
-
A sub
|
992
|
+
A sub-block can also have a different execution mode if it is declared using `seq`, which will force sequential execution mode, and `par` which will force parallel execution mode. For example, in the following code a parallel sub-block is declared within a sequential one:
|
1015
993
|
|
1016
994
|
```ruby
|
1017
995
|
system :with_sequential_behavior do
|
@@ -1024,7 +1002,7 @@ system :with_sequential_behavior do
|
|
1024
1002
|
end
|
1025
1003
|
```
|
1026
1004
|
|
1027
|
-
Sub blocks have their
|
1005
|
+
Sub blocks have their scope so that it is possible to declare signals without colliding with existing ones. For example, it is possible to
|
1028
1006
|
declare three different inner signals all called `sig` as follows:
|
1029
1007
|
|
1030
1008
|
```ruby
|
@@ -1065,7 +1043,7 @@ system :shift16 do
|
|
1065
1043
|
end
|
1066
1044
|
```
|
1067
1045
|
|
1068
|
-
In the example above, the order of the transmission statements is of no consequence. This is not the case for the following example,
|
1046
|
+
In the example above, the order of the transmission statements is of no consequence. This is not the case for the following example, which implements the same register using a sequential block. In this second example, putting the statement `reg[0] <= din` in the last place would have led to an invalid functionality for a shift register.
|
1069
1047
|
|
1070
1048
|
```ruby
|
1071
1049
|
system :shift16 do
|
@@ -1120,7 +1098,7 @@ end
|
|
1120
1098
|
( a <= b+1 ).at(clk.posedge)
|
1121
1099
|
```
|
1122
1100
|
|
1123
|
-
For sake of consistency, this operator can also be applied
|
1101
|
+
For sake of consistency, this operator can also be applied to block statements as follows, but it is probably less readable than the standard declaration of behaviors:
|
1124
1102
|
|
1125
1103
|
```ruby
|
1126
1104
|
( seq do
|
@@ -1162,17 +1140,56 @@ end
|
|
1162
1140
|
```
|
1163
1141
|
|
1164
1142
|
__Note__:
|
1165
|
-
- While of no practical use for simple circuit
|
1143
|
+
- While of no practical use for simple circuit descriptions, this feature can be used in advanced generic component descriptions.
|
1144
|
+
|
1145
|
+
|
1146
|
+
### Reconfiguration
|
1147
|
+
|
1148
|
+
In HDLRuby, dynamically reconfigurable devices are modeled by instances having more than one system. Adding systems to an instance is done as follows:
|
1149
|
+
|
1150
|
+
```ruby
|
1151
|
+
<instance>.choice(<list of named systems>)
|
1152
|
+
```
|
1153
|
+
|
1154
|
+
For example, assuming systems `sys0`, `sys1` and `sys2` have been previously declared a device named `dev012` able to be reconfigured to one of these three systems would be declared as follows (the connections of the instance, omitted in the example, can be done as usual):
|
1155
|
+
|
1156
|
+
```ruby
|
1157
|
+
sys0 :dev012 # dev012 is at first a standard instance of sys0
|
1158
|
+
dev012.choice(conf1: sys1, conf2: sys2) # Now dev012 is reconfigurable
|
1159
|
+
```
|
1160
|
+
|
1161
|
+
After the code above, instance `dev012` can be dynamically reconfigured to `sys0`, `sys1`, and `sys2` with respective names `dev012`, `conf1`, and `conf2`.
|
1162
|
+
|
1163
|
+
__Note:__
|
1164
|
+
The name of the initial system in the reconfigurations is set to be the name of the instance.
|
1165
|
+
|
1166
|
+
A reconfigurable instance can then be reconfigured using the command `configure` as follows:
|
1167
|
+
|
1168
|
+
```ruby
|
1169
|
+
<instance>.configure(<name or index>)
|
1170
|
+
```
|
1171
|
+
|
1172
|
+
In the code above, the argument of `configure` can either be the name of the configuration as previously declared with `choice`, or its index in order of declaration. For example in the following code, instance `dev012` is reconfigured to system `sys1`, then system `sys0` the system `sys2`:
|
1173
|
+
|
1174
|
+
```ruby
|
1175
|
+
dev012.configure(:conf1)
|
1176
|
+
!1000.ns
|
1177
|
+
dev012.configure(:dev012)
|
1178
|
+
!1000.ns
|
1179
|
+
dev012.configure(2)
|
1180
|
+
```
|
1181
|
+
|
1182
|
+
These reconfiguration commands are treated as regular RTL statements in HDLRuby and are supported by the simulator. However, in the current version of the HDLRuby, these statements are ignored when generating Verilog HDL or VHDL code.
|
1166
1183
|
|
1167
1184
|
|
1168
1185
|
## Events
|
1169
1186
|
<a name="events"></a>
|
1170
1187
|
|
1171
|
-
Each behavior of a system is associated with a list of events, called
|
1188
|
+
Each behavior of a system is associated with a list of events, called a sensitivity list, that specifies when the behavior is to be executed. An event is associated with a signal and represents the instants when the signal reaches a given state.
|
1172
1189
|
|
1173
|
-
There are three kinds of
|
1190
|
+
There are three kinds of events: positive edge events represent the instants when their corresponding signals vary from 0 to 1, and negative edge events
|
1174
1191
|
represent the instants when their corresponding signals vary from 1 to 0 and the change events represent the instants when their corresponding signals vary.
|
1175
|
-
Events are declared directly from the signals, using the `posedge` operator for positive edge, the `negedge` operator for negative edge, and the `change` operator for change. For example, the following code declares 3 behaviors activated respectively on the positive edge, the negative edge and any change of the `clk` signal.
|
1192
|
+
Events are declared directly from the signals, using the `posedge` operator for a positive edge, the `negedge` operator for a negative edge, and the `change` operator for change. For example, the following code declares 3 behaviors activated respectively on the positive edge, the negative edge, and any change of the `clk` signal.
|
1176
1193
|
|
1177
1194
|
```ruby
|
1178
1195
|
inner :clk
|
@@ -1197,8 +1214,8 @@ __Note:__
|
|
1197
1214
|
<a name="statements"></a>
|
1198
1215
|
|
1199
1216
|
Statements are the basic elements of a behavioral description. They are regrouped in blocks that specify their execution mode (parallel or sequential).
|
1200
|
-
There are four kinds of statements: the transmit statement
|
1201
|
-
that changes the execution flow of the behavior, the block statement (described earlier) and the inner signal declaration.
|
1217
|
+
There are four kinds of statements: the transmit statement which computes expressions and sends the result to the target signals, the control statement
|
1218
|
+
that changes the execution flow of the behavior, the block statement (described earlier), and the inner signal declaration.
|
1202
1219
|
|
1203
1220
|
__Note__:
|
1204
1221
|
|
@@ -1209,7 +1226,7 @@ __Note__:
|
|
1209
1226
|
|
1210
1227
|
A transmit statement is declared using the arrow operator `<=` within a behavior. Its right value is the expression to compute and its left value is a reference to the target signals (or parts of signals), i.e., the signals (or part of signals) that receive the computation result.
|
1211
1228
|
|
1212
|
-
For example, following code transmits the value `3` to signal `s0` and the sum of the values of signals `i0` and `i1` to the first four bits of signal `s1`:
|
1229
|
+
For example, the following code transmits the value `3` to signal `s0` and the sum of the values of signals `i0` and `i1` to the first four bits of signal `s1`:
|
1213
1230
|
|
1214
1231
|
```ruby
|
1215
1232
|
s0 <= 3
|
@@ -1285,7 +1302,7 @@ that the current synthesis tools do not really synthesize hardware from such loo
|
|
1285
1302
|
__Notes__:
|
1286
1303
|
|
1287
1304
|
- HDLRuby being based on Ruby, it is highly recommended to avoid `for` or `while` constructs and to use enumerators instead.
|
1288
|
-
- The Ruby `if` and `case` statements can also be used, but they do not represent any hardware.
|
1305
|
+
- The Ruby `if` and `case` statements can also be used, but they do not represent any hardware. They are executed when the corresponding system is instantiated. For example, the following code will display `Hello world!` when the described system is instantiated, provided the generic parameter `param` is not nil.
|
1289
1306
|
|
1290
1307
|
```ruby
|
1291
1308
|
system :say_hello do |param = nil|
|
@@ -1298,38 +1315,38 @@ __Notes__:
|
|
1298
1315
|
## Types
|
1299
1316
|
<a name="types"></a>
|
1300
1317
|
|
1301
|
-
Each signal and each expression is associated with a data type
|
1302
|
-
bit
|
1318
|
+
Each signal and each expression is associated with a data type that describes the kind of value it can represent. In HDLRuby, the data types represent
|
1319
|
+
bit-vectors associated with the way they should be interpreted, i.e., as bit strings, unsigned values, signed values, or hierarchical contents.
|
1303
1320
|
|
1304
1321
|
### Type construction
|
1305
1322
|
|
1306
|
-
There are five basic types, `bit`, `signed`, `unsigned`, `integer
|
1323
|
+
There are five basic types, `bit`, `signed`, `unsigned`, `integer`, and `float` that represent respectively single bit logical values, single-bit unsigned values, single-bit signed values, Ruby integer values, and Ruby floating-point values (double precision). The first three types are HW and support four-valued logic, whereas the two last ones are SW (but are compatible with HW) and only support Boolean logic. Ruby integers can represent any element of **Z** (the mathematical integers) and have for that purpose a variable bit-width.
|
1307
1324
|
|
1308
1325
|
|
1309
1326
|
The other types are built from them using a combination of the two following
|
1310
1327
|
type operators.
|
1311
1328
|
|
1312
|
-
__The vector operator__ `[]` is used for building types representing vectors of single or multiple other types. A vector whose elements have all the same type
|
1329
|
+
__The vector operator__ `[]` is used for building types representing vectors of single or multiple other types. A vector whose elements have all the same type is declared as follows:
|
1313
1330
|
|
1314
1331
|
```ruby
|
1315
1332
|
<type>[<range>]
|
1316
1333
|
```
|
1317
1334
|
|
1318
1335
|
The `<range>` of a vector type indicates the position of the starting and ending bits.
|
1319
|
-
|
1336
|
+
An `n..0` range can also be abbreviated to `n+1`. For instance, the two following types are identical:
|
1320
1337
|
|
1321
1338
|
```ruby
|
1322
1339
|
bit[7..0]
|
1323
1340
|
bit[8]
|
1324
1341
|
```
|
1325
1342
|
|
1326
|
-
A vector of multiple types, also called tuple, is declared as follows:
|
1343
|
+
A vector of multiple types, also called a tuple, is declared as follows:
|
1327
1344
|
|
1328
1345
|
```ruby
|
1329
1346
|
[<type 0>, <type 1>, ... ]
|
1330
1347
|
```
|
1331
1348
|
|
1332
|
-
For example, the following code declares the type of the vectors made of an 8-bit logical, a 16-bit signed and a 16-bit unsigned values:
|
1349
|
+
For example, the following code declares the type of the vectors made of an 8-bit logical, a 16-bit signed, and a 16-bit unsigned values:
|
1333
1350
|
|
1334
1351
|
```ruby
|
1335
1352
|
[ bit[8], signed[16], unsigned[16] ]
|
@@ -1341,7 +1358,7 @@ __The structure operator__ `{}` is used for building hierarchical types made of
|
|
1341
1358
|
{ <name 0>: <type 0>, <name 1>: <type 1>, ... }
|
1342
1359
|
```
|
1343
1360
|
|
1344
|
-
For instance, the following code declares a hierarchical type with an 8-bit
|
1361
|
+
For instance, the following code declares a hierarchical type with an 8-bit subtype named `header` and a 24-bit subtype named `data`:
|
1345
1362
|
|
1346
1363
|
```ruby
|
1347
1364
|
{ header: bit[7..0], data: bit[23..0] }
|
@@ -1391,9 +1408,9 @@ end
|
|
1391
1408
|
|
1392
1409
|
### Type compatibility and conversion
|
1393
1410
|
|
1394
|
-
The basis of all the types in HDLRuby is the vector of bits (
|
1411
|
+
The basis of all the types in HDLRuby is the vector of bits (bit vector) where each bit can have four values: 0, 1, Z, and X (for undefined). Bit vectors are by default unsigned but can be set to be signed. When performing computations between signals of different bit-vector types, the shorter signal is extended to the size of the larger one preserving its sign if it is signed.
|
1395
1412
|
|
1396
|
-
While the underlying structure of any HDLRuby type is the
|
1413
|
+
While the underlying structure of any HDLRuby type is the bit vector, complex types can be defined. When using such types in computational expressions and assignments they are first implicitly converted to an unsigned bit vector of the same size.
|
1397
1414
|
|
1398
1415
|
## Expressions
|
1399
1416
|
<a name="expressions"></a>
|
@@ -1405,7 +1422,7 @@ They include [immediate values](#values), [reference to signals](#references) an
|
|
1405
1422
|
### Immediate values
|
1406
1423
|
<a name="values"></a>
|
1407
1424
|
|
1408
|
-
The immediate values of HDLRuby can represent vectors of `bit`, `unsigned
|
1425
|
+
The immediate values of HDLRuby can represent vectors of `bit`, `unsigned`, and `signed`, and integer or floating-point numbers. They are prefixed by a `_` character and include a header that indicates the vector type and the base used for representing the value, followed by a numeral representing the value. The bit width of a value is obtained by default from the width of the numeral, but it is also possible to enforce it in the header.
|
1409
1426
|
|
1410
1427
|
The vector type specifiers are the followings:
|
1411
1428
|
|
@@ -1413,7 +1430,7 @@ The vector type specifiers are the followings:
|
|
1413
1430
|
|
1414
1431
|
- `u`: `unsigned` type, (equivalent to `b` and can be used for avoiding confusion with the binary specifier),
|
1415
1432
|
|
1416
|
-
- `s`: `signed` type, the last figure is sign
|
1433
|
+
- `s`: `signed` type, the last figure is sign-extended if required by the binary, octal, and hexadecimal bases, but not for the decimal base.
|
1417
1434
|
|
1418
1435
|
The base specifiers are the followings:
|
1419
1436
|
|
@@ -1440,7 +1457,7 @@ _s8o144
|
|
1440
1457
|
|
1441
1458
|
__Notes__:
|
1442
1459
|
|
1443
|
-
- Ruby immediate values can also be used, their bit width is automatically adjusted to match the data type of the expression they are used in. Please notice this adjusting may change the value of the immediate, for example the following code will set `sig` to 4 instead of 100:
|
1460
|
+
- Ruby immediate values can also be used, their bit width is automatically adjusted to match the data type of the expression they are used in. Please notice this adjusting may change the value of the immediate, for example, the following code will set `sig` to 4 instead of 100:
|
1444
1461
|
|
1445
1462
|
```ruby
|
1446
1463
|
[3..0].inner :sig
|
@@ -1451,7 +1468,7 @@ __Notes__:
|
|
1451
1468
|
### References
|
1452
1469
|
<a name="references"></a>
|
1453
1470
|
|
1454
|
-
References are expressions used to designate signals
|
1471
|
+
References are expressions used to designate signals or a part of signals.
|
1455
1472
|
|
1456
1473
|
The simplest reference is simply the name of a signal. It designates the signal corresponding to this name in the current scope. For instance, in the
|
1457
1474
|
following code, inner signal `sig0` is declared, and therefore the name *sig0* becomes a reference to designate this signal.
|
@@ -1464,13 +1481,13 @@ inner :sig0
|
|
1464
1481
|
sig0 <= 0
|
1465
1482
|
```
|
1466
1483
|
|
1467
|
-
For designating a signal of another system, or a sub
|
1484
|
+
For designating a signal of another system, or a sub-signal in a hierarchical signal, you can use the `.` operator as follows:
|
1468
1485
|
|
1469
1486
|
```ruby
|
1470
1487
|
<parent name>.<signal name>
|
1471
1488
|
```
|
1472
1489
|
|
1473
|
-
For example, in the following code, input signal `d` of system instance `dff0` is connected to sub
|
1490
|
+
For example, in the following code, input signal `d` of system instance `dff0` is connected to sub-signal `sub0` of hierarchical signal `sig`.
|
1474
1491
|
|
1475
1492
|
```ruby
|
1476
1493
|
system :dff do
|
@@ -1568,7 +1585,7 @@ __Notes__:
|
|
1568
1585
|
|
1569
1586
|
- The operator precedence is the one of Ruby.
|
1570
1587
|
|
1571
|
-
- Ruby does not allow to override the `&&`, the `||` and the `?:` operators so that they are not present in HDLRuby. Instead of the `?:` operator, HDLRuby provides the more general multiplex operator `mux`. However, HDLRuby does not
|
1588
|
+
- Ruby does not allow to override the `&&`, the `||` and the `?:` operators so that they are not present in HDLRuby. Instead of the `?:` operator, HDLRuby provides the more general multiplex operator `mux`. However, HDLRuby does not provide any replacement for the `&&` and the `||` operators, please refer to section [Logic operators](#logic) for a justification about this issue.
|
1572
1589
|
|
1573
1590
|
#### Assignment operators
|
1574
1591
|
<a name="assignment"></a>
|
@@ -1595,19 +1612,19 @@ __Notes__:
|
|
1595
1612
|
|
1596
1613
|
- The `<`, `>`, `<=` and `>=` operators can only be used on vectors of `bit`, `unsigned` or `signed` values, `integer` or `float` values.
|
1597
1614
|
|
1598
|
-
- When compared, values of type different from vector of `signed` and from `float` are considered as vectors of `unsigned`.
|
1615
|
+
- When compared, values of a type different from the vector of `signed` and from `float` are considered as vectors of `unsigned`.
|
1599
1616
|
|
1600
1617
|
|
1601
1618
|
#### Logic and shift operators
|
1602
1619
|
<a name="logic"></a>
|
1603
1620
|
|
1604
|
-
In HDLRuby, the logic operators are all bitwise. For performing Boolean computations, it is necessary to use single
|
1621
|
+
In HDLRuby, the logic operators are all bitwise. For performing Boolean computations, it is necessary to use single-bit values. The bitwise logic binary operators are `&`, `|`, and `^`, and the unary one is `~`. They have the same meaning as their Ruby equivalents.
|
1605
1622
|
|
1606
|
-
__Note__: there
|
1623
|
+
__Note__: there are two reasons why there are no Boolean operators
|
1607
1624
|
|
1608
|
-
1. Ruby language does not support redefinition of the Boolean operators
|
1625
|
+
1. Ruby language does not support the redefinition of the Boolean operators
|
1609
1626
|
|
1610
|
-
2. In Ruby, each value
|
1627
|
+
2. In Ruby, each value that is not `false` nor `nil` is assumed to be true. This is perfectly relevant for software, but not for hardware where the basic data types are bit vectors. Hence, it seemed preferable to support Boolean computation for one-bit values only, which can be done through bitwise operations.
|
1611
1628
|
|
1612
1629
|
The shift operators are `<<` and `>>` and have the same meaning as their Ruby equivalent. They do not change the bit width and preserve the sign for `signed` values.
|
1613
1630
|
|
@@ -1618,7 +1635,7 @@ The rotation operators are `rl` and `rr` for respectively left and right bit rot
|
|
1618
1635
|
<expression>.rr(<other expression>)
|
1619
1636
|
```
|
1620
1637
|
|
1621
|
-
For example, for rotating left signal `sig` 3 times, the following code can be used:
|
1638
|
+
For example, for rotating the left signal `sig` 3 times, the following code can be used:
|
1622
1639
|
|
1623
1640
|
```ruby
|
1624
1641
|
sig.rl(3)
|
@@ -1632,7 +1649,7 @@ selection operators](#concat) for more details about these operators.
|
|
1632
1649
|
<a name="conversion"></a>
|
1633
1650
|
|
1634
1651
|
The conversion operators are used to change the type of an expression.
|
1635
|
-
There are two kinds of such operators: the type pun that
|
1652
|
+
There are two kinds of such operators: the type pun that does not change the raw value of the expression and the type cast that changes the raw value.
|
1636
1653
|
|
1637
1654
|
The type puns include `to_bit`, `to_unsigned` and `to_signed` that convert expressions of any type type to vectors of respectively `bit`, `unsigned` and `signed` elements. For example, the following code converts an expression of hierarchical type to an 8-bit signed vector:
|
1638
1655
|
|
@@ -1641,12 +1658,12 @@ The type puns include `to_bit`, `to_unsigned` and `to_signed` that convert expre
|
|
1641
1658
|
sig.to_bit <= _b01010011
|
1642
1659
|
```
|
1643
1660
|
|
1644
|
-
The type casts change both the type and the value and are used to adjust the width of the types. They can only be applied to vectors of `bit`, `signed
|
1661
|
+
The type casts change both the type and the value and are used to adjust the width of the types. They can only be applied to vectors of `bit`, `signed`, or `unsinged` and can only increase the bit width (bit width can be truncated using the selection operator, please refer to the [next section](#concat)).
|
1645
1662
|
These operators comprise the bit width conversions: `ljust`, `rjust`, `zext` and `sext`.
|
1646
1663
|
|
1647
1664
|
More precisely, the bit width conversions operate as follows:
|
1648
1665
|
|
1649
|
-
- `ljust` and `rjust` increase the size from respectively the left or the right side of the bit vector. They take as argument the width of the new type and the value (0 or 1) of the bits to add. For example, the following code increases the size of `sig0` to 12 bits by adding 1 on the right:
|
1666
|
+
- `ljust` and `rjust` increase the size from respectively the left or the right side of the bit vector. They take as an argument the width of the new type and the value (0 or 1) of the bits to add. For example, the following code increases the size of `sig0` to 12 bits by adding 1 on the right:
|
1650
1667
|
|
1651
1668
|
```ruby
|
1652
1669
|
[7..0].inner :sig0
|
@@ -1655,7 +1672,7 @@ More precisely, the bit width conversions operate as follows:
|
|
1655
1672
|
sig1 <= sig0.ljust(12,1)
|
1656
1673
|
```
|
1657
1674
|
|
1658
|
-
- `zext` increases the size by adding several 0 bits on the most significant bit side, this side depending on the endianness of the expression. This conversion takes as argument the width of the resulting type. For example, the following code increases the size of `sig0` to 12 bits by adding 0 on the left:
|
1675
|
+
- `zext` increases the size by adding several 0 bits on the most significant bit side, this side depending on the endianness of the expression. This conversion takes as an argument the width of the resulting type. For example, the following code increases the size of `sig0` to 12 bits by adding 0 on the left:
|
1659
1676
|
|
1660
1677
|
```ruby
|
1661
1678
|
signed[7..0].inner :sig0
|
@@ -1664,7 +1681,7 @@ More precisely, the bit width conversions operate as follows:
|
|
1664
1681
|
sig1 <= sig0.zext(12)
|
1665
1682
|
```
|
1666
1683
|
|
1667
|
-
- `sext` increases the size by duplicating the most significant bit, the side of the extension depending on the endianness of the expression. This conversion takes as argument the width of the resulting type. For example, the following code increases the size of `sig0` to 12 bits by adding 1 on the right:
|
1684
|
+
- `sext` increases the size by duplicating the most significant bit, the side of the extension depending on the endianness of the expression. This conversion takes as an argument the width of the resulting type. For example, the following code increases the size of `sig0` to 12 bits by adding 1 on the right:
|
1668
1685
|
|
1669
1686
|
```ruby
|
1670
1687
|
signed[0..7].inner :sig0
|
@@ -1795,15 +1812,15 @@ Where:
|
|
1795
1812
|
|
1796
1813
|
__Notes__:
|
1797
1814
|
|
1798
|
-
- Functions have their
|
1815
|
+
- Functions have their scope, so any declaration within a function is local. It is also forbidden to declare interface signals (input, output, or inout) within a function.
|
1799
1816
|
|
1800
|
-
- Like the Ruby proc objects, the last statement of a function's code serves as return value. For instance, the following function returns `1` (in this example the function does not have any argument):
|
1817
|
+
- Like the Ruby proc objects, the last statement of a function's code serves as the return value. For instance, the following function returns `1` (in this example the function does not have any argument):
|
1801
1818
|
|
1802
1819
|
```ruby
|
1803
1820
|
function :one { 1 }
|
1804
1821
|
```
|
1805
1822
|
|
1806
|
-
- Functions can accept any kind of object as argument, including variadic arguments or blocks of code as shown below with a function
|
1823
|
+
- Functions can accept any kind of object as an argument, including variadic arguments or blocks of code as shown below with a function that applies the code passed as an argument to all the variadic arguments of `args`:
|
1807
1824
|
|
1808
1825
|
```ruby
|
1809
1826
|
function :apply do |*args, &code|
|
@@ -1840,7 +1857,7 @@ Where:
|
|
1840
1857
|
* `code` is the code of the function.
|
1841
1858
|
|
1842
1859
|
These functions are called the same way HDLRuby functions are called, but this operation pastes the code of the function as is within the code.
|
1843
|
-
Moreover, these functions do not have any scope so
|
1860
|
+
Moreover, these functions do not have any scope so any inner signal or instance declared within them will be added to the object they are invoked in.
|
1844
1861
|
|
1845
1862
|
For example, the following function will add input `in0` to any system where it is invoked:
|
1846
1863
|
|
@@ -1891,7 +1908,7 @@ Ruby functions can be compared to the macros of the C languages: they are more f
|
|
1891
1908
|
### Time values
|
1892
1909
|
<a name="time_val"></a>
|
1893
1910
|
|
1894
|
-
In HDLRuby, time values can be created using the time operators: `s` for seconds, `ms` for millisecond, `us` for microseconds, `ns` for nanoseconds, `ps` for picoseconds. For example, the followings are all indicating one second
|
1911
|
+
In HDLRuby, time values can be created using the time operators: `s` for seconds, `ms` for a millisecond, `us` for microseconds, `ns` for nanoseconds, `ps` for picoseconds. For example, the followings are all indicating one second:
|
1895
1912
|
|
1896
1913
|
```ruby
|
1897
1914
|
1.s
|
@@ -1905,7 +1922,7 @@ In HDLRuby, time values can be created using the time operators: `s` for seconds
|
|
1905
1922
|
### Time behaviors and time statements
|
1906
1923
|
<a name="time_beh"></a>
|
1907
1924
|
|
1908
|
-
Like the other HDL, HDLRuby provides specific statements that
|
1925
|
+
Like the other HDL, HDLRuby provides specific statements that model the advance of time. These statements are not synthesizable and are used for simulating the environment of a hardware component. For sake of clarity, such statements are only allowed in explicitly non-synthesizable behavior declared using the `timed` keyword as follows.
|
1909
1926
|
|
1910
1927
|
```ruby
|
1911
1928
|
timed do
|
@@ -1916,7 +1933,7 @@ end
|
|
1916
1933
|
A time behavior does not have any sensitivity list, but it can include any statement supported by a standard behavior in addition to the time statements.
|
1917
1934
|
There are two kinds of such statements:
|
1918
1935
|
|
1919
|
-
- The `wait` statements: such a statement blocks the execution of the behavior for the time given in argument. For example, the following code waits 10ns before proceeding:
|
1936
|
+
- The `wait` statements: such a statement blocks the execution of the behavior for the time given in the argument. For example, the following code waits for 10ns before proceeding:
|
1920
1937
|
|
1921
1938
|
```ruby
|
1922
1939
|
wait(10.ns)
|
@@ -1928,7 +1945,7 @@ There are two kinds of such statements:
|
|
1928
1945
|
!10.ns
|
1929
1946
|
```
|
1930
1947
|
|
1931
|
-
- The `repeat` statements: such a statement takes as argument a time value and a block. The execution of the block is repeated until the delay given by the time value argument expires. For example, the following code executes repeatedly the inversion of the `clk` signal every 10 nanoseconds for 10 seconds (i.e., it simulates a clock signal for 10 seconds):
|
1948
|
+
- The `repeat` statements: such a statement takes as argument a time value and a block. The execution of the block is repeated until the delay that is given by the time value argument expires. For example, the following code executes repeatedly the inversion of the `clk` signal every 10 nanoseconds for 10 seconds (i.e., it simulates a clock signal for 10 seconds):
|
1932
1949
|
|
1933
1950
|
```ruby
|
1934
1951
|
repeat(10.s) do
|
@@ -1944,7 +1961,7 @@ sequential blocks. The execution semantic is the following:
|
|
1944
1961
|
|
1945
1962
|
- A sequential block in a time behavior is executed sequentially.
|
1946
1963
|
|
1947
|
-
- A parallel block in a time behavior is executed in semi-parallel fashion as follows:
|
1964
|
+
- A parallel block in a time behavior is executed in a semi-parallel fashion as follows:
|
1948
1965
|
|
1949
1966
|
1. Statements are grouped in sequence until a time statement is met.
|
1950
1967
|
|
@@ -1961,7 +1978,7 @@ sequential blocks. The execution semantic is the following:
|
|
1961
1978
|
|
1962
1979
|
### Using Ruby in HDLRuby
|
1963
1980
|
|
1964
|
-
Since HDLRuby is pure Ruby code, the constructs of Ruby can be freely used without any compatibility
|
1981
|
+
Since HDLRuby is pure Ruby code, the constructs of Ruby can be freely used without any compatibility issues. Moreover, this Ruby code will not interfere with the synthesizability of the design. It is then possible to define Ruby classes, methods, or modules whose execution generates constructs of
|
1965
1982
|
HDLRuby.
|
1966
1983
|
|
1967
1984
|
|
@@ -1985,7 +2002,7 @@ For example, the following code describes an empty system with two generic param
|
|
1985
2002
|
system(:nothing) { |a,b| }
|
1986
2003
|
```
|
1987
2004
|
|
1988
|
-
The generic parameters can be anything: values, data types, signals, systems, Ruby variables, and so on. For example, the following system uses generic argument `t` as a type for an input signal, generic argument `w` as a bit range for an output signal and generic argument `s` as a system used for creating instance `sI` whose input and output signals `i` and `o` are connected respectively to signals `isig` and `osig`.
|
2005
|
+
The generic parameters can be anything: values, data types, signals, systems, Ruby variables, and so on. For example, the following system uses generic argument `t` as a type for an input signal, generic argument `w` as a bit range for an output signal, and generic argument `s` as a system used for creating instance `sI` whose input and output signals `i` and `o` are connected respectively to signals `isig` and `osig`.
|
1989
2006
|
|
1990
2007
|
```ruby
|
1991
2008
|
system :something do |t,w,s|
|
@@ -2018,7 +2035,7 @@ For example, the following code describes a bit-vector type with generic number
|
|
2018
2035
|
type(:bitvec) { |width| bit[width] }
|
2019
2036
|
```
|
2020
2037
|
|
2021
|
-
Like with the systems, the generic parameters of types can be any kind of
|
2038
|
+
Like with the systems, the generic parameters of types can be any kind of object, and it is also possible to use variadic arguments.
|
2022
2039
|
|
2023
2040
|
|
2024
2041
|
|
@@ -2026,13 +2043,13 @@ Like with the systems, the generic parameters of types can be any kind of object
|
|
2026
2043
|
|
2027
2044
|
##### Specializing generic systems
|
2028
2045
|
|
2029
|
-
A generic system is specialized by invoking its name and passing as argument the values corresponding to the generic arguments as follows:
|
2046
|
+
A generic system is specialized by invoking its name and passing as an argument the values corresponding to the generic arguments as follows:
|
2030
2047
|
|
2031
2048
|
```ruby
|
2032
2049
|
<system name>(<generic argument value's list>)
|
2033
2050
|
```
|
2034
2051
|
|
2035
|
-
If
|
2052
|
+
If fewer values are provided than the number of generic arguments, the system is partially specialized. However, only a fully specialized system can be instantiated.
|
2036
2053
|
|
2037
2054
|
A specialized system can also be used for inheritance. For example, assuming system `sys` has 2 generic arguments, it can be specialized and used for building system `subsys` as follows:
|
2038
2055
|
|
@@ -2053,23 +2070,23 @@ end
|
|
2053
2070
|
|
2054
2071
|
__Note:__
|
2055
2072
|
|
2056
|
-
- In the example above, generic parameter `param` of `subsys_gen` is used for specializing system `sys`.
|
2073
|
+
- In the example above, the generic parameter `param` of `subsys_gen` is used for specializing system `sys`.
|
2057
2074
|
|
2058
2075
|
|
2059
2076
|
##### Specializing generic types
|
2060
2077
|
|
2061
|
-
A generic type is specialized by invoking its name and passing as argument the values corresponding to the generic arguments as follows:
|
2078
|
+
A generic type is specialized by invoking its name and passing as an argument the values corresponding to the generic arguments as follows:
|
2062
2079
|
|
2063
2080
|
```ruby
|
2064
2081
|
<type name>(<generic argument value's list>)
|
2065
2082
|
```
|
2066
2083
|
|
2067
|
-
If
|
2084
|
+
If fewer values are provided than the number of generic arguments, the type is partially specialized. However, only a fully specialized type can be used for declaring signals.
|
2068
2085
|
|
2069
2086
|
|
2070
2087
|
##### Use of signals as generic parameters
|
2071
2088
|
|
2072
|
-
Signals passed as generic arguments to systems can be used for making generic connections to the instance of the system. For that purpose, the generic argument has to be declared as input, output or inout port in the body of the system as follows:
|
2089
|
+
Signals passed as generic arguments to systems can be used for making generic connections to the instance of the system. For that purpose, the generic argument has to be declared as input, output, or inout port in the body of the system as follows:
|
2073
2090
|
|
2074
2091
|
```ruby
|
2075
2092
|
system :<system_name> do |sig|
|
@@ -2078,7 +2095,7 @@ system :<system_name> do |sig|
|
|
2078
2095
|
end
|
2079
2096
|
```
|
2080
2097
|
|
2081
|
-
In the code above, `sig` is a generic argument assumed to be a signal. The second line declares the port to which sig will connected to when instantiating. From there, port `my_sig` can be used like any other port of the system. Such a system is
|
2098
|
+
In the code above, `sig` is a generic argument assumed to be a signal. The second line declares the port to which sig will be connected to when instantiating. From there, port `my_sig` can be used like any other port of the system. Such a system is then instantiated as follows:
|
2082
2099
|
|
2083
2100
|
```ruby
|
2084
2101
|
system_name(some_sig) :<instance_name>
|
@@ -2096,7 +2113,7 @@ In the code above, `some_sig` is a signal available in the current context. This
|
|
2096
2113
|
In HDLRuby, a system can inherit from the content of one or several other parent systems using the `include` command as follows: `include <list of
|
2097
2114
|
systems>`. Such an include can be put anywhere in the body of a system, but the resulting content will be accessible only after this command.
|
2098
2115
|
|
2099
|
-
For example, the following code describes first a simple D-FF, and then
|
2116
|
+
For example, the following code describes first a simple D-FF, and then uses it to describe a FF with an additional reversed output (`qb`):
|
2100
2117
|
|
2101
2118
|
```ruby
|
2102
2119
|
system :dff do
|
@@ -2135,7 +2152,7 @@ end
|
|
2135
2152
|
|
2136
2153
|
__Note__:
|
2137
2154
|
|
2138
|
-
* As a matter of implementation, HDLRuby systems can be viewed as sets of methods used for accessing various constructs (signals, instances). Hence inheritance in HDLRuby is closer the Ruby mixin mechanism than to a true software inheritance.
|
2155
|
+
* As a matter of implementation, HDLRuby systems can be viewed as sets of methods used for accessing various constructs (signals, instances). Hence inheritance in HDLRuby is closer to the Ruby mixin mechanism than to a true software inheritance.
|
2139
2156
|
|
2140
2157
|
|
2141
2158
|
#### About inner signals and system instances
|
@@ -2193,11 +2210,11 @@ section.
|
|
2193
2210
|
|
2194
2211
|
#### Shadowed signals and instances
|
2195
2212
|
|
2196
|
-
It is possible in HDLRuby to declare a signal or an instance whose name is identical to one used in one of the included systems. In such a case, the corresponding construct of the included system is still present, but it is not directly accessible even if exported, they are said to be shadowed.
|
2213
|
+
It is possible in HDLRuby to declare a signal or an instance whose name is identical to the one used in one of the included systems. In such a case, the corresponding construct of the included system is still present, but it is not directly accessible even if exported, they are said to be shadowed.
|
2197
2214
|
|
2198
|
-
|
2215
|
+
To access the shadowed signals or instances, a system must be reinterpreted as the relevant parent system using the `as` operator as follows: `as(system)`.
|
2199
2216
|
|
2200
|
-
For example, in the following code signal `db` of system `dff_db` is shadowed by signal `db` of system `dff_shadow`, but it is accessed using the `as` operator.
|
2217
|
+
For example, in the following code signal, `db` of system `dff_db` is shadowed by signal `db` of system `dff_shadow`, but it is accessed using the `as` operator.
|
2201
2218
|
|
2202
2219
|
```ruby
|
2203
2220
|
system :dff_db do
|
@@ -2300,9 +2317,9 @@ fix32.define_operator(:*) do |left,right|
|
|
2300
2317
|
end
|
2301
2318
|
```
|
2302
2319
|
|
2303
|
-
Please notice, that in the code above, the left value has been
|
2320
|
+
Please notice, that in the code above, the left value has been cast to a plain bit-vector to avoid the infinite recursive call of the `*` operator.
|
2304
2321
|
|
2305
|
-
|
2322
|
+
Operators can also be overloaded with generic types. However, in such a case, the generic argument must also be present in the list of arguments of the overloaded operators.
|
2306
2323
|
For instance, let us consider the following fixed-point type of variable width (and whose decimal point is set at the half of its bit range):
|
2307
2324
|
|
2308
2325
|
```ruby
|
@@ -2321,7 +2338,7 @@ end
|
|
2321
2338
|
|
2322
2339
|
### Predicate and access methods
|
2323
2340
|
|
2324
|
-
|
2341
|
+
To get information about the current state of the hardware description HDLRuby provides the following predicates:
|
2325
2342
|
|
2326
2343
|
| predicate name | predicate type | predicate meaning |
|
2327
2344
|
| :--- | :--- | :--- |
|
@@ -2353,7 +2370,7 @@ Several enumerators are also provided for accessing the internals of the current
|
|
2353
2370
|
|
2354
2371
|
HDLRuby allows to declare global signals the same way system's signals are declared, but outside the scope of any system. After being declared, these signals are accessible directly from within any hardware construct.
|
2355
2372
|
|
2356
|
-
|
2373
|
+
To ease the design of standardized libraries, the following global signals are defined by default:
|
2357
2374
|
|
2358
2375
|
| signal name | signal type | signal function |
|
2359
2376
|
| :--- | :--- | :--- |
|
@@ -2370,7 +2387,7 @@ __Note__:
|
|
2370
2387
|
### Defining and executing Ruby methods within HDLRuby constructs
|
2371
2388
|
<a name="method"></a>
|
2372
2389
|
|
2373
|
-
Like with any Ruby program it is possible to define and execute methods anywhere in HDLRuby using the standard Ruby syntax. When defined, a method is attached to the enclosing HDLRuby construct. For instance, when defining a method when declaring a system, it
|
2390
|
+
Like with any Ruby program it is possible to define and execute methods anywhere in HDLRuby using the standard Ruby syntax. When defined, a method is attached to the enclosing HDLRuby construct. For instance, when defining a method when declaring a system, it can be used within this system only, while when defining a method outside any construct, it can be used everywhere in the HDLRuby description.
|
2374
2391
|
|
2375
2392
|
A method can include HDLRuby code in which case the resulting hardware is appended to the current construct. For example, the following code adds a connection between `sig0` and `sig1` in system `sys0`, and transmission between `sig0` and `sig1` in the behavior of `sys1`.
|
2376
2393
|
|
@@ -2398,9 +2415,9 @@ end
|
|
2398
2415
|
|
2399
2416
|
__Warning__:
|
2400
2417
|
|
2401
|
-
- In the above example, the semantic of `some_arrow` changes depending on where it is invoked from
|
2418
|
+
- In the above example, the semantic of `some_arrow` changes depending on where it is invoked from, e.g., within a system, it is a connection, within a behavior, it is a transmission.
|
2402
2419
|
|
2403
|
-
- Using Ruby methods for describing hardware might lead to weak code, for example the
|
2420
|
+
- Using Ruby methods for describing hardware might lead to weak code, for example, in the following code, the method declares `in0` as an input signal. Hence, while used in `sys0` no problem happens, an exception will be raised for `sys1` because a signal `in0` is already declared and will also be raised for `sys2` because it is not possible to declare an input from within a behavior.
|
2404
2421
|
|
2405
2422
|
```ruby
|
2406
2423
|
def in_decl
|
@@ -2423,7 +2440,7 @@ __Warning__:
|
|
2423
2440
|
end
|
2424
2441
|
```
|
2425
2442
|
|
2426
|
-
Like any other Ruby method, methods defined in HDLRuby support variadic arguments
|
2443
|
+
Like any other Ruby method, methods defined in HDLRuby support variadic arguments named arguments, and block arguments. For example, the following method can be used to connect a driver to multiple signals:
|
2427
2444
|
|
2428
2445
|
```ruby
|
2429
2446
|
def mconnect(driver, *signals)
|
@@ -2464,11 +2481,11 @@ end
|
|
2464
2481
|
|
2465
2482
|
In the code above:
|
2466
2483
|
|
2467
|
-
- the default initialization of `rst` to `$rst` allows
|
2484
|
+
- the default initialization of `rst` to `$rst` allows resetting the counter even if no such signal is provided as an argument.
|
2468
2485
|
|
2469
|
-
- `sub` ensures that the `count` signal
|
2486
|
+
- `sub` ensures that the `count` signal does not conflict with another signal with the same name.
|
2470
2487
|
|
2471
|
-
- the `instance_eval` keyword is a standard Ruby method that executes the block passed as argument in context.
|
2488
|
+
- the `instance_eval` keyword is a standard Ruby method that executes the block passed as an argument in context.
|
2472
2489
|
|
2473
2490
|
The following is an example that switches a LED on after 1000000 clock cycles using the previously defined `after` ruby method:
|
2474
2491
|
|
@@ -2491,13 +2508,13 @@ __Note__:
|
|
2491
2508
|
|
2492
2509
|
### Dynamic description
|
2493
2510
|
|
2494
|
-
When describing a system, it is possible to disconnect or
|
2511
|
+
When describing a system, it is possible to disconnect or completely undefine a signal or an instance.
|
2495
2512
|
|
2496
2513
|
|
2497
2514
|
## Extending HDLRuby
|
2498
2515
|
<a name="extend"></a>
|
2499
2516
|
|
2500
|
-
Like any Ruby classes, the constructs of HDLRuby can be dynamically extended. If it is not recommended to change their internal structure, it is possible to add methods to them for extension.
|
2517
|
+
Like any Ruby classes, the constructs of HDLRuby can be dynamically extended. If it is not recommended to change their internal structure, it is possible to add methods to them for an extension.
|
2501
2518
|
|
2502
2519
|
### Extending HDLRuby constructs globally
|
2503
2520
|
|
@@ -2534,7 +2551,7 @@ The following table gives the class of each construct of HDLRuby.
|
|
2534
2551
|
|
2535
2552
|
### Extending HDLRuby constructs locally
|
2536
2553
|
|
2537
|
-
By local extension of a hardware construct, we mean that while the construct will be changed, all the other constructs will remain unchanged. This is achieved like in Ruby by accessing the
|
2554
|
+
By local extension of a hardware construct, we mean that while the construct will be changed, all the other constructs will remain unchanged. This is achieved like in Ruby by accessing the Eigen class using the `singleton_class` method and extending it using the `class_eval` method. For example, with the following code, only system `dff` will respond to method `interface_size`:
|
2538
2555
|
|
2539
2556
|
```ruby
|
2540
2557
|
dff.singleton_class.class_eval do
|
@@ -2570,7 +2587,7 @@ end
|
|
2570
2587
|
|
2571
2588
|
### Modifying the generation behavior
|
2572
2589
|
|
2573
|
-
The main purpose of allowing global and local extensions for hardware constructs is to give the user the possibility
|
2590
|
+
The main purpose of allowing global and local extensions for hardware constructs is to give the user the possibility to implement its synthesis methods. For example, one may want to implement some algorithm for a given kind of system. For that purpose, the user can define an abstract system (without any hardware content), that holds the specific algorithm as follows:
|
2574
2591
|
|
2575
2592
|
```ruby
|
2576
2593
|
system(:my_base) {}
|
@@ -2582,7 +2599,7 @@ my_base.singleton_instance.class_eval do
|
|
2582
2599
|
end
|
2583
2600
|
```
|
2584
2601
|
|
2585
|
-
Then, when this system named `my_base` is included
|
2602
|
+
Then, when this system named `my_base` is included in another system, this latter will inherit from the algorithms implemented inside method `my_generation` as shown in the following code:
|
2586
2603
|
|
2587
2604
|
```ruby
|
2588
2605
|
system :some_system, my_base do
|
@@ -2626,7 +2643,7 @@ This way, calling directly `to_low` will automatically use `my_generation`.
|
|
2626
2643
|
# Standard library
|
2627
2644
|
<a name="library"></a>
|
2628
2645
|
|
2629
|
-
The standard libraries are included
|
2646
|
+
The standard libraries are included in the module `Std`.
|
2630
2647
|
They can be loaded as follows, where `<library name>` is the name of the
|
2631
2648
|
library:
|
2632
2649
|
|
@@ -2645,9 +2662,9 @@ include HDLRuby::High::Std
|
|
2645
2662
|
## Clocks
|
2646
2663
|
<a name="clocks"></a>
|
2647
2664
|
|
2648
|
-
The `clocks` library provides utilities for
|
2665
|
+
The `clocks` library provides utilities for easier handling of clock synchronizations.
|
2649
2666
|
|
2650
|
-
It adds the possibility to multiply events by integer. The result is a new event whose frequency is divided by the integer multiplicand. For example, the following code describes a D-FF that memorizes each three clock cycles.
|
2667
|
+
It adds the possibility to multiply events by an integer. The result is a new event whose frequency is divided by the integer multiplicand. For example, the following code describes a D-FF that memorizes each three clock cycles.
|
2651
2668
|
|
2652
2669
|
```ruby
|
2653
2670
|
require 'std/clocks'
|
@@ -2669,7 +2686,7 @@ __Note__: this library does generate all the RTL code for the circuit handling t
|
|
2669
2686
|
|
2670
2687
|
This library provides two new constructs for implementing synthesizable wait statements.
|
2671
2688
|
|
2672
|
-
The first construct is the `after` statement that activates a block after a given number of
|
2689
|
+
The first construct is the `after` statement that activates a block after a given number of clock cycles is passed. Its syntax is the following:
|
2673
2690
|
|
2674
2691
|
```ruby
|
2675
2692
|
after(<number>,<clock>,<reset>)
|
@@ -2683,7 +2700,7 @@ Where:
|
|
2683
2700
|
|
2684
2701
|
This statement can be used either inside or outside a clocked behavior. When used within a clocked behavior, the clock event of the behavior is used for the counter unless specified otherwise. When used outside such a behavior, the clock is the global default clock `$clk`. In both cases, the reset is the global reset `$rst` unless specified otherwise.
|
2685
2702
|
|
2686
|
-
The second construct is the `before` statement that activates a block until a given number of
|
2703
|
+
The second construct is the `before` statement that activates a block until a given number of clock cycles is passed. Its syntax and usage are identical to the `after` statement.
|
2687
2704
|
|
2688
2705
|
|
2689
2706
|
## Decoder
|
@@ -2703,7 +2720,7 @@ Where `signal` is the signal to decode and `block` is a procedure block (i.e., R
|
|
2703
2720
|
entry(<pattern>) <block>
|
2704
2721
|
```
|
2705
2722
|
|
2706
|
-
Where `pattern` is a string describing the pattern to match for the entry, and `block` is a procedure block describing the actions (some HDLRuby code) that are performed when the entry matches. The string describing the pattern can include `0` and `1` characters for specifying a specific value for the corresponding bit, or any alphabetical character for specifying a field in the pattern. The fields in the pattern can then be used by name in the block describing the action. When a letter is used several times within a pattern, the corresponding bits are concatenated
|
2723
|
+
Where `pattern` is a string describing the pattern to match for the entry, and `block` is a procedure block describing the actions (some HDLRuby code) that are performed when the entry matches. The string describing the pattern can include `0` and `1` characters for specifying a specific value for the corresponding bit, or any alphabetical character for specifying a field in the pattern. The fields in the pattern can then be used by name in the block describing the action. When a letter is used several times within a pattern, the corresponding bits are concatenated and are used as a signal multi-bit signal in the block.
|
2707
2724
|
|
2708
2725
|
For example, the following code describes a decoder for signal `ir` with two entries, the first one computing the sum of fields `x` and `y` and assigning the result to signal `s` and the second one computing the sum of fields `x` `y` and `z` and assigning the result to signal `s`:
|
2709
2726
|
|
@@ -2714,7 +2731,7 @@ decoder(ir) do
|
|
2714
2731
|
end
|
2715
2732
|
```
|
2716
2733
|
|
2717
|
-
|
2734
|
+
It can be noticed for field `z` in the example above that the bits are not required to be contiguous.
|
2718
2735
|
|
2719
2736
|
## FSM
|
2720
2737
|
<a name="fsm"></a>
|
@@ -2727,9 +2744,9 @@ A finite state machine can be declared anywhere provided it is outside a behavio
|
|
2727
2744
|
fsm(<event>,<reset>,<mode>) <block>
|
2728
2745
|
```
|
2729
2746
|
|
2730
|
-
Where `event` is the event (rising falling edge of a signal) activating the state transitions, `rst` is the reset signal, and `mode` is the default execution mode and `block` is the execution block describing the states of the FSM. This last parameter can be either `:sync` for synchronous (Moore type) or `:async` for asynchronous (Mealy type).
|
2747
|
+
Where `event` is the event (rising or falling edge of a signal) activating the state transitions, `rst` is the reset signal, and `mode` is the default execution mode and `block` is the execution block describing the states of the FSM. This last parameter can be either `:sync` for synchronous (Moore type) or `:async` for asynchronous (Mealy type).
|
2731
2748
|
|
2732
|
-
The states of
|
2749
|
+
The states of an FSM are described as follows:
|
2733
2750
|
|
2734
2751
|
```ruby
|
2735
2752
|
<kind>(<name>) <block>
|
@@ -2750,19 +2767,19 @@ default <block>
|
|
2750
2767
|
|
2751
2768
|
Where `block` is the action to execute.
|
2752
2769
|
|
2753
|
-
State transitions are by default set to be from one state to the following in the description order. If no more transition is declared the next one is the first declared transition. A specific transition is defined using the `goto` statement as last statement of the action block as follows:
|
2770
|
+
State transitions are by default set to be from one state to the following in the description order. If no more transition is declared the next one is the first declared transition. A specific transition is defined using the `goto` statement as the last statement of the action block as follows:
|
2754
2771
|
|
2755
2772
|
```ruby
|
2756
2773
|
goto(<condition>,<names>)
|
2757
2774
|
```
|
2758
2775
|
|
2759
|
-
Where `condition` is a signal whose value is used as index for
|
2776
|
+
Where `condition` is a signal whose value is used as an index for selecting the target state among the ones specified in the `names` list. For example, the following statement indicates to go to the state named `st_a` if the `cond` is 0, `st_b` if the condition is 1, and `st_c` if the condition is 2, otherwise this specific transition is ignored:
|
2760
2777
|
|
2761
2778
|
```ruby
|
2762
2779
|
goto(cond,:st_a,:st_b,:st_c)
|
2763
2780
|
```
|
2764
2781
|
|
2765
|
-
Several goto statements can be used, the last one having priority provided it is taken (i.e., its condition
|
2782
|
+
Several goto statements can be used, the last one having priority provided it is taken (i.e., its condition corresponds to one of the target states). If no goto is taken, the next transition is the next declared one.
|
2766
2783
|
|
2767
2784
|
For example, the following code describes a FSM describing a circuit that checks if two buttons (`but_a` and `but_b`) are pressed and released in sequence for activating an output signal (`ok`):
|
2768
2785
|
|
@@ -2792,7 +2809,7 @@ end
|
|
2792
2809
|
## Fixed-point (fixpoint)
|
2793
2810
|
<a name="fixpoint"></a>
|
2794
2811
|
|
2795
|
-
This library provides a new fixed point set of data types. These new data types can be bit vectors, unsigned or signed
|
2812
|
+
This library provides a new fixed point set of data types. These new data types can be bit vectors, unsigned or signed values and are declared respectively as follows:
|
2796
2813
|
|
2797
2814
|
```ruby
|
2798
2815
|
bit[<integer part range>,<fractional part range>]
|
@@ -2800,21 +2817,21 @@ unsigned[<integer part range>,<fractional part range>]
|
|
2800
2817
|
signed[<integer part range>,<fractional part range>]
|
2801
2818
|
```
|
2802
2819
|
|
2803
|
-
For example a signed 4-bit integer part 4-bit fractional part fixed point inner signal named `sig` can be declared as follows:
|
2820
|
+
For example, a signed 4-bit integer part 4-bit fractional part fixed point inner signal named `sig` can be declared as follows:
|
2804
2821
|
|
2805
2822
|
```ruby
|
2806
2823
|
bit[4,4].inner :sig
|
2807
2824
|
```
|
2808
2825
|
|
2809
|
-
When performing computation with fixed
|
2826
|
+
When performing computation with fixed-point types, HDLRuby ensures that the result's decimal point position is correct.
|
2810
2827
|
|
2811
|
-
In addition to the fixed point data type, a method is added to the literal objects (Numeric) to convert them to fixed
|
2828
|
+
In addition to the fixed point data type, a method is added to the literal objects (Numeric) to convert them to fixed-point representation:
|
2812
2829
|
|
2813
2830
|
```ruby
|
2814
2831
|
<litteral>.to_fix(<number of bits after the decimal point>)
|
2815
2832
|
```
|
2816
2833
|
|
2817
|
-
For example the following code converts a floating
|
2834
|
+
For example, the following code converts a floating-point value to a fixed point value with 16 bits after the decimal point:
|
2818
2835
|
|
2819
2836
|
```
|
2820
2837
|
3.178.to_fix(16)
|
@@ -2824,14 +2841,14 @@ For example the following code converts a floating point value to a fixed point
|
|
2824
2841
|
## Channel
|
2825
2842
|
<a name="channel"></a>
|
2826
2843
|
|
2827
|
-
This library provides a unified interface to complex communication protocols through a new kind of
|
2844
|
+
This library provides a unified interface to complex communication protocols through a new kind of component called the channels that abstract the details of communication protocols. The channels can be used similarly to the ports of a system and are used through a unified interface so that changing the kind of channel, i.e., the communication protocol, does not require any modification of the code.
|
2828
2845
|
|
2829
2846
|
### Using a channel
|
2830
2847
|
|
2831
2848
|
A channel is used similarly to a pipe: it has an input where data can be written and an output where data can be read. The ordering of the data and the synchronization depend on the internals of the channel, e.g., a channel can be FIFO or LIFO. The interaction with the channel is done using the following methods:
|
2832
2849
|
|
2833
|
-
* `write(<args>) <block>`: write to the channel and execute `block` when `write` completes. `args` is a list of arguments required for performing the write that
|
2834
|
-
* `read(<args>) <block>`: read the channel and execute `block` when the read completes. `args` is a list of arguments required for performing the write that
|
2850
|
+
* `write(<args>) <block>`: write to the channel and execute `block` when `write` completes. `args` is a list of arguments required for performing the write that depends on the channel.
|
2851
|
+
* `read(<args>) <block>`: read the channel and execute `block` when the read completes. `args` is a list of arguments required for performing the write that depends on the channel.
|
2835
2852
|
|
2836
2853
|
|
2837
2854
|
For example, a system sending successive 8-bit values through a channel can be described as follows:
|
@@ -2853,15 +2870,15 @@ system :producer8 do |channel|
|
|
2853
2870
|
end
|
2854
2871
|
```
|
2855
2872
|
|
2856
|
-
__Note__: In the code above, the channel is passed as generic argument of the system.
|
2873
|
+
__Note__: In the code above, the channel is passed as a generic argument of the system.
|
2857
2874
|
|
2858
2875
|
The access points to a channel can also be handled individually by declaring ports using the following methods:
|
2859
2876
|
|
2860
|
-
* `input <name>`: declares a port for reading from the channel and
|
2861
|
-
* `output <name>`: declares a port for writing to the channel and
|
2862
|
-
* `inout <name>`: declares a port for reading and writing to the channel and
|
2877
|
+
* `input <name>`: declares a port for reading from the channel and associates them to `name` if any
|
2878
|
+
* `output <name>`: declares a port for writing to the channel and associates them to `name` if any
|
2879
|
+
* `inout <name>`: declares a port for reading and writing to the channel and associates them to `name` if any
|
2863
2880
|
|
2864
|
-
Such port can then be accessed using the same `read` and `write` method of a channel, the difference being that they can also be configured for new access
|
2881
|
+
Such port can then be accessed using the same `read` and `write` method of a channel, the difference being that they can also be configured for new access procedures using the `wrap` method:
|
2865
2882
|
|
2866
2883
|
* `wrap(<args>) <code>`: creates a new port whose read or write procedure has the elements of `<args>` and the ones produced by `<code>` assign to the arguments of the read or write procedure.
|
2867
2884
|
|
@@ -2873,11 +2890,11 @@ For example, assuming `mem` is a channel whose read and write access have as arg
|
|
2873
2890
|
|
2874
2891
|
### Channel branches
|
2875
2892
|
|
2876
|
-
Some
|
2893
|
+
Some channels may include several branches, they are accessed by name using the following method:
|
2877
2894
|
|
2878
|
-
* `branch(<name>)`: gets branch named `name` from the channel. This name can be
|
2895
|
+
* `branch(<name>)`: gets branch named `name` from the channel. This name can be any ruby object (e.g., a number) but it will be converted internally to a ruby symbol.
|
2879
2896
|
|
2880
|
-
A branch is a full
|
2897
|
+
A branch is a full-fledge channel and is used identically. For instance, the following code gets access to branch number 0 of channel `ch`, gets its inputs port, reads it, and put the result in signal `val` on the rising edges of signal `clk`:
|
2881
2898
|
|
2882
2899
|
```ruby
|
2883
2900
|
br = ch.branch(0)
|
@@ -2887,13 +2904,13 @@ par(clk.posedge) { br.read(val) }
|
|
2887
2904
|
|
2888
2905
|
### Declaring a channel
|
2889
2906
|
|
2890
|
-
A new channel is declared
|
2907
|
+
A new channel is declared using the keyword `channel` as follows:
|
2891
2908
|
|
2892
2909
|
```ruby
|
2893
2910
|
channel <name> <block>
|
2894
2911
|
```
|
2895
2912
|
|
2896
|
-
Where `name` is the name of the channel and `block` is a procedure block describing the channel. This block can contain any HDLRuby code, and is comparable to the content of a block describing a system with the difference that it does not have standard input, output and inout ports are declared differently and that it supports following additional keywords:
|
2913
|
+
Where `name` is the name of the channel and `block` is a procedure block describing the channel. This block can contain any HDLRuby code, and is comparable to the content of a block describing a system with the difference that it does not have standard input, output, and inout ports are declared differently, and that it supports the following additional keywords:
|
2897
2914
|
|
2898
2915
|
* `reader_input <list of names>`: declares the input ports on the reader side. The list must give the names of the inner signals of the channel that can be read using the reader procedure.
|
2899
2916
|
* `reader_output <list of names>`: declares the output ports on the reader side. The list must give the names of the inner signals of the channel that can be written using the reader procedure.
|
@@ -2901,20 +2918,20 @@ Where `name` is the name of the channel and `block` is a procedure block describ
|
|
2901
2918
|
* `writer_input <list of names>`: declares the input ports on the writer side. The list must give the names of the inner signals of the channel that can be read using the writer procedure.
|
2902
2919
|
* `writer_output <list of names>`: declares the output ports on the writer side. The list must give the names of the inner signals of the channel that can be written using the writer procedure.
|
2903
2920
|
* `writer_inout <list of names>`: declares the inout ports on the writer side. The list must give the names of the inner signals of the channel that can be written using the writer procedure.
|
2904
|
-
* `accesser_input <list of names>`: declares the input ports on both the reader and writer
|
2905
|
-
* `accesser_output <list of names>`: declares the output ports on both the reader and writer
|
2906
|
-
* `accesser_inout <list of names>`: declares the inout ports on both the reader and writer
|
2921
|
+
* `accesser_input <list of names>`: declares the input ports on both the reader and writer sides. The list must give the names of the inner signals of the channel that can be read using the writer procedure.
|
2922
|
+
* `accesser_output <list of names>`: declares the output ports on both the reader and writer sides. The list must give the names of the inner signals of the channel that can be written using the writer procedure.
|
2923
|
+
* `accesser_inout <list of names>`: declares the inout ports on both the reader and writer sides. The list must give the names of the inner signals of the channel that can be written using the writer procedure.
|
2907
2924
|
* `reader <block>`: defines the reader's access procedure.
|
2908
|
-
This procedure is invoked by method `read` of the channel (please refer to the previous example).
|
2925
|
+
This procedure is invoked by the method `read` of the channel (please refer to the previous example).
|
2909
2926
|
The first argument of the block must be the following:
|
2910
2927
|
- `blk`: the block to execute when the read completes.
|
2911
|
-
Other arguments can be freely defined
|
2928
|
+
Other arguments can be freely defined and will be required by the `read` method.
|
2912
2929
|
* `writer < block>`: defines the writer's access procedure.
|
2913
|
-
This procedure is invoked by method `write` of the channel (please refer to the previous example).
|
2930
|
+
This procedure is invoked by the method `write` of the channel (please refer to the previous example).
|
2914
2931
|
The first argument of the block must be the following:
|
2915
2932
|
- `blk`: the block to execute when the write completes.
|
2916
|
-
Other arguments can be freely defined
|
2917
|
-
* `brancher(name) <block>`: defines branch named +name+ described in `block`. The content of block can be any content valid for a channel, with the additional possibility to access the internals of the upper channel.
|
2933
|
+
Other arguments can be freely defined and will be required by the `write` command.
|
2934
|
+
* `brancher(name) <block>`: defines branch named +name+ described in `block`. The content of the block can be any content valid for a channel, with the additional possibility to access the internals of the upper channel.
|
2918
2935
|
|
2919
2936
|
For example, a channel implemented by a simple register of generic type `typ`, that can be set to 0 using the `reset` command can be described as follows:
|
2920
2937
|
|
@@ -2947,7 +2964,7 @@ end
|
|
2947
2964
|
|
2948
2965
|
__Notes__:
|
2949
2966
|
|
2950
|
-
* The described channel assumes that
|
2967
|
+
* The described channel assumes that the `write` method of the channel is invoked within a clocked process (otherwise, the register will become a latch).
|
2951
2968
|
* The described channel supports the `read` and `write` methods to be invoked with or without a block.
|
2952
2969
|
|
2953
2970
|
|
@@ -2957,7 +2974,7 @@ Like systems, a channel must be instantiated for being used, and the instantiati
|
|
2957
2974
|
<channel name> :<instance name>
|
2958
2975
|
```
|
2959
2976
|
|
2960
|
-
And in case there
|
2977
|
+
And in case there is a generic parameter, the instantiation procedure is as follows:
|
2961
2978
|
|
2962
2979
|
```ruby
|
2963
2980
|
<channel name>(:<instance name>).(<generic parameters>)
|
@@ -2999,17 +3016,7 @@ end
|
|
2999
3016
|
|
3000
3017
|
__Note__:
|
3001
3018
|
|
3002
|
-
* The code of the circuits, in the examples `producer8`, `consumer8
|
3003
|
-
|
3004
|
-
|
3005
|
-
## Reconf
|
3006
|
-
<a name="reconf"></a>
|
3007
|
-
|
3008
|
-
This library provides a unified interface to partially (or dynamically) reconfigurable devices.
|
3009
|
-
|
3010
|
-
__Warning__:
|
3011
|
-
|
3012
|
-
While the framework of this library is completed, not target reconfigurable device is defined yet.
|
3019
|
+
* The code of the circuits, in the examples `producer8`, `consumer8`, and `producer_consummer8` is independent of the content of the channel. For example, the sample `with_channel.rb` (please see [sample](#sample)) use the same circuits with a channel implementing handshaking.
|
3013
3020
|
|
3014
3021
|
|
3015
3022
|
## Pipeline
|
@@ -3035,7 +3042,7 @@ The naming convention of the samples is the following:
|
|
3035
3042
|
|
3036
3043
|
* `<name>.rb`: default type of sample.
|
3037
3044
|
* `<name>_gen.rb`: generic parameters are required for processing the sample.
|
3038
|
-
* `<name>_bench.rb`: sample including a simulation benchmark, these are the only samples that can be simulated using `hdrcc -S`. Please notice that such sample cannot be converted to VHDL
|
3045
|
+
* `<name>_bench.rb`: sample including a simulation benchmark, these are the only samples that can be simulated using `hdrcc -S`. Please notice that such a sample cannot be converted to VHDL or Verilog HDL yet.
|
3039
3046
|
|
3040
3047
|
|
3041
3048
|
# Contributing
|
@@ -3055,5 +3062,5 @@ Bug reports and pull requests are welcome on GitHub at https://github.com/civol/
|
|
3055
3062
|
|
3056
3063
|
# License
|
3057
3064
|
|
3058
|
-
The gem is available as open
|
3065
|
+
The gem is available as open-source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
3059
3066
|
|