|
1 | | -# HDL |
| 1 | +# HIRL Hardware Description Language |
| 2 | + |
2 | 3 | [](https://github.com/Jacajack/hdl/actions/workflows/ci.yml) [](https://codecov.io/gh/Jacajack/hdl) |
3 | 4 |
|
4 | | -A hardware description language named after a funny bird. |
| 5 | +HIRL (working name: _Hardware Intermediate Representation Language_) is a proof-of-concept, declarative hardware description language optimized for RTL coding, aiming to provide modern Rust-like syntax and more restrictive semantics protecting the user from typical errors. |
| 6 | + |
| 7 | +Notable features: |
| 8 | + - **Syntax inspired by Rust and C++** |
| 9 | + - **Sensitivity semantics in the type system provide basic CDC validation** |
| 10 | + - **Restrictive signal width and signedness semantics** |
| 11 | + - **Bi-directional type deduction** - not all types need to be explicitly specified in assignments |
| 12 | + - **No implicit conversions** - potentially harmful implicit conversions are not allowed |
| 13 | + - **Generic constructs** compiled to equivalent generic System Verilog code |
| 14 | + - **Builtin elab phase** ensuring proper use of signals (i.e. no double drivers, no dangling inputs etc.) |
| 15 | + - Interoperability with System Verilog |
| 16 | + |
| 17 | +## Examples |
| 18 | + |
| 19 | +This section presents some basic code examples. More code samples can be found in the [tests](/tests/) directory. |
| 20 | + |
| 21 | +### Combinational full adder |
| 22 | + |
| 23 | +```sv |
| 24 | +// Interface definition |
| 25 | +module full_adder { |
| 26 | + // All inputs and outputs are asynchronous |
| 27 | + input async a; |
| 28 | + input async b; |
| 29 | + input async cin; |
| 30 | + output async cout; |
| 31 | + output async q; |
| 32 | +} |
| 33 | +
|
| 34 | +// Module logic |
| 35 | +impl full_adder { |
| 36 | + cout = (a & b) | (cin & (a ^ b)); |
| 37 | + q = a ^ b ^ cin; |
| 38 | +} |
| 39 | +``` |
| 40 | + |
| 41 | +### Simple counter |
| 42 | + |
| 43 | +```sv |
| 44 | +module simple_counter{ |
| 45 | + // Clock input |
| 46 | + input clock clk; |
| 47 | +
|
| 48 | + // Asynchronous reset signal (active low) |
| 49 | + input async wire nreset; |
| 50 | +
|
| 51 | + // Combinational enable signal (clock domain is clk) |
| 52 | + input comb(clk) wire enable; |
| 53 | +
|
| 54 | + // Synchronous 16-bit output bus |
| 55 | + output unsigned sync(clk) bus<16> data; |
| 56 | +} |
| 57 | +
|
| 58 | +impl simple_counter { |
| 59 | + // data is 16 bits wide, 1u1 is 1 bit wide. |
| 60 | + // Addition result is 17-bit and therefore needs |
| 61 | + // to be explicitly truncated with trunc() builtin function |
| 62 | + bus<16> counter_next = trunc(data + 1u1); |
| 63 | +
|
| 64 | + // Register storing counter's value |
| 65 | + reg counter{ |
| 66 | + clk, // Auto-connected to `clk` |
| 67 | + nreset, // Auto-connected to `nreset` |
| 68 | + en: enable, // Enable the register with `enable` signal |
| 69 | + next: counter_next, // Next value for the register |
| 70 | + data, // Output is auto-connected to `data` |
| 71 | + }; |
| 72 | +} |
| 73 | +``` |
| 74 | + |
| 75 | +## Building |
| 76 | + |
| 77 | +Use Cargo for building. The compiler has builtin command line help. For practical example of use please also see [this Makefile](/tests/input_sim/Makefile). |
5 | 78 |
|
6 | | -### Coverage graphs |
| 79 | +## Coverage graphs |
7 | 80 |
|
8 | 81 | <table> |
9 | 82 | <tr><td> |
|
0 commit comments