|
Language
|
HDLmaker supports a C like language that is used to generate complex design. The language supports integer and string arithmetic, conditional branching, and loops.
Variables
HDLmaker has two data types, integers and strings. Ints are 32 bit signed integers, strings are radix 36 numbers which are described below. Variables are declared with the #int and the #string statements.
#int i,j,k,index;
#string a_bus,b_bus;
The initial value of a variable is inherited from the caller, i.e. if a top file declares a variable foo and assigns a value to it and then calls bar.top the initial value that the module bar.top sees is the value assigned in the calling module. Initial values may be assigned from the command line with the switches -int,-string and -variables. -int and -string are used for individula variables, -variables calls a file which assigns initial values to multiple variables.
hdlmaker -int foo 12 -string my_str THIS_IS_MY_String -variables var.txt bar.top
The format for a variables file is,
#int var_a 10;
#int var_b 15;
#string str_var_a hello_world;
#string str_var_b glad_to_see_you;
Int
Ints are signed longs. HDLmaker supports the full set of C integer and logical operations.
+
-
*
/
&
|
^
!
~
++
--
+=
-=
*=
/=
&=
|=
^=
>>
<<
<> (Rotate)
Conditionals
>
<
>=
<=
==
Strings
Strings are limited the characters a-z 0-9 and _. The radix26 variable determines if radix 26 or radix 36 arithmetic is used. For arithmetic operations strings are treated as either radix 36 numbers where the characters have the decimal value:
0-9 0-9
a-z 10-25
or as radix 26 numbers where the characters have the decimal values,
a-z 0-25
The underscore is used as a field delimiter. To illustrate how string arithmetic works consider the following two radix 36 examples.
az + 1
--------
b0
a_z +1
--------
a_10
In the first example az is treated as a single number and the carry out of z +1 is added to the next character. In the second example the field delimiter separates the first field, a, from the second, z. In this case z + 1 is 10.
To understand the difference between radix 26 and radix 36 arithmetic consider the following examples
radix 26
z + 1
-----
ba
radix 36
z + 1
-----
10
The following operations are supported on strings,
+
-
*
/
~
&
|
^
$ (concatenate)
++
--
+=
-=
*=
/=
Conditionals
==
>=
<=
<
>
Builtin Variables
HDLmaker parameters/switche values are available as builtin variables. The Built in variables are,
Variable
|
Type
|
Description
|
Values
|
hdl_simulate_mode
|
int
|
Simulate or Synthesis mode
|
0 Synthesis
1 Simulate
|
hdl_simulator
|
string
|
Simulator
|
"leapfrog",
"verilogxl",
"modeltech",
"vcs",
"finsim",
"ncverilog",
"synopsysvss",
"ncsim"
|
hdl_synthesys
|
string
|
Synthesis tool
|
"synopsys",
"synplicity",
"fpgaexpress",
"exemplar",
"leonardo",
"rtlc",
"xst",
"quartus",
"precision"
|
hdl_family
|
string
|
FPGA family
|
virtex,virtex2...
|
hdl_package
|
string
|
FPGA package
|
ff1152...
|
hdl_speed
|
string
|
FPGA speed
|
 |
hdl_company
|
string
|
Company name
|
 |
hdl_engineer
|
string
|
Engineers name
|
 |
hdl_language
|
string
|
HDL language
|
verilog,vhdl
|
Lexical Scope
Variable values and names are copied down to lower levels of the hierarchy, no values are returned. Passing a parameter from one level to the next is done by name. To make this clear consider the following example:
#int num_rows, num_cols;
#assign num_rows = 12;
#assign num_cols = 16;
#insert "sub_level.top";
Inside sub_level.top we may use the values as follows:
#int i,j;
#for(i=0;i<num_rows;i++)
{
#for(j=0;j<num_cols;j++)
{
....
}
}
#assign
Assignment statements begin with the keyword #assign.
#assign x = y + z;
#assign myname = first_name $ last_name;
#if, else
#if is identical to the C if statement.
#if(i == j)
{
}
else
{
}
#for
#for(i=0;i<num_rows;i++)
{
}
#while
#while(i < 100)
{
#assign i++;
}
Code generation example
Below is an example of code generation using HDLmaker's macro language. In connection statements HDLmaker takes names literally unless the expression starts with either a quoted string or with a #, in which case it evaulates the expression.
loop.top
#module "loop";
#include "loop.pin";
#int i;
#string reg;
#insert "dregce32.v",
connect ce = ce[0],
connect q[31:0] = reg_a[31:0];
#assign reg = "reg_a";
#for(i=0;i<2;i++)
{
#insert "dregce32.v",
connect ce = ce[#i+1],
connect d[31:0] = "reg_a" + i[31:0],
connect q[31:0] = "reg_b" + i[31:0];
#assign reg++;
}
#insert "dregce32.v",
connect ce = ce[#i+1],
connect d[31:0] = #reg[31:0];
loop.v
module loop(
ce,
d,
gblreset,
q,
sysclk
);
//-- IO Declarations
input [3:0] ce;
input [31:0] d;
input gblreset;
output [31:0] q;
input sysclk;
//-- Signal Declarations
wire [31:0] reg_a;
wire [31:0] reg_b;
wire [31:0] reg_c;
//-- Component Instance dregce32_1
dregce32 dregce32_1
(
.ce (ce[0]),
.d ({d[31:0]}),
.gblreset (gblreset),
.sysclk (sysclk),
.q ({reg_a[31:0]})
);
//-- Component Instance dregce32_2
dregce32 dregce32_2
(
.ce (ce[1]),
.d ({reg_a[31:0]}),
.gblreset (gblreset),
.sysclk (sysclk),
.q ({reg_b[31:0]})
);
//-- Component Instance dregce32_3
dregce32 dregce32_3
(
.ce (ce[2]),
.d ({reg_b[31:0]}),
.gblreset (gblreset),
.sysclk (sysclk),
.q ({reg_c[31:0]})
);
//-- Component Instance dregce32_4
dregce32 dregce32_4
(
.ce (ce[3]),
.d ({reg_c[31:0]}),
.gblreset (gblreset),
.sysclk (sysclk),
.q ({q[31:0]})
);
endmodule
loop.vhd
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
use IEEE.std_logic_unsigned.all;
entity loop is
port (
ce_pin :in std_logic_vector (3 downto 0);
d_pin :in std_logic_vector (31 downto 0);
gblreset_pin :in std_logic;
q_pin :buffer std_logic_vector (31 downto 0);
sysclk_pin :in std_logic
);
end loop;
architecture BEHAVIOR of loop is
component dregce32
port (
sysclk,ce,gblreset : in std_logic ;
d : in std_logic_vector (31 downto 0);
q : buffer std_logic_vector (31 downto 0)
);
end component;
--// signals begin here
signal ce : std_logic_vector (3 downto 0);
signal d : std_logic_vector (31 downto 0);
signal gblreset : std_logic;
signal q : std_logic_vector (31 downto 0);
signal reg_a : std_logic_vector (31 downto 0);
signal reg_b : std_logic_vector (31 downto 0);
signal reg_c : std_logic_vector (31 downto 0);
signal sysclk : std_logic;
begin
dregce32_1: dregce32
port map (
sysclk => sysclk,
ce => ce (0),
gblreset => gblreset,
d (31 downto 0) => d (31 downto 0),
q (31 downto 0) => reg_a (31 downto 0)
);
dregce32_2: dregce32
port map (
sysclk => sysclk,
ce => ce (1),
gblreset => gblreset,
d (31 downto 0) => reg_a (31 downto 0),
q (31 downto 0) => reg_b (31 downto 0)
);
dregce32_3: dregce32
port map (
sysclk => sysclk,
ce => ce (2),
gblreset => gblreset,
d (31 downto 0) => reg_b (31 downto 0),
q (31 downto 0) => reg_c (31 downto 0)
);
dregce32_4: dregce32
port map (
sysclk => sysclk,
ce => ce (3),
gblreset => gblreset,
d (31 downto 0) => reg_c (31 downto 0),
q (31 downto 0) => q (31 downto 0)
);
end;
|