11 Function Unit Interface

Function unit interfaces follow a certain de facto standard in TCE. Here is an example of a such interface:

entity fu_add_sub_eq_gt_always_1 is
  generic (
    dataw : integer := 32;
    busw  : integer := 32);
  port (
    -- trigger port / operand2 input port
    t1data   : in std_logic_vector (dataw-1 downto 0);
    t1opcode : in std_logic_vector (1 downto 0);
    t1load   : in std_logic;
    -- operand1 input port
    o1data : in std_logic_vector (dataw-1 downto 0);
    o1load : in std_logic;
    -- result output port
    r1data : out std_logic_vector (busw-1 downto 0);
    -- control signals
    glock  : in  std_logic;
    rstx   : in  std_logic;
    clk    : in  std_logic);
end fu_add_sub_eq_gt_always_1;

As you can see the actual implementation interface has more inputs/outputs than the architecture model of a FU. Architecture input ports are called o1data and t1data and the output port is called r1data. In addition there are load ports, operation code port and some control signals.

It is good practice to use (integer) generics for the port widths in the data I/O ports. This makes the managing of Hardware Database (HDB) easier because you can use the name of the generic to define port width formulas instead of using magic numbers. Whether the value of a generic is constant or parametrizable depends on how you define it in the HDB. In the example entity declaration we have used two different generics, data width (dataw) and bus width (busw). The input data ports depend on the dataw and the output port is defined using busw. You can also use only one generic but with 2 generics you can define different widths for input and output data if needed.

The names you set for the ports in VHDL code is up to you. When you define an FU implementation in HDB you'll have to do port mapping where you map the VHDL implementation names to the HDB counterparts. I strongly recommend to use a consistent naming convention to avoid confusion. HDBEditor prefills the common control signal dialog fields with the defacto standard names. If you use your own naming style for the ports I still recommend to use the standard names for control signals which are used in the example above (glock = Global Lock, rstx = reset (x stands for active low), clk = clock).

The input ports have also load ports. The load signal is active high when the input value of an input port is valid and should be read (most probably to a register inside the FU). If the input port is also a trigger port the operation should be initiated.

If the FU has multiple operations there is also an operation code port in the interface. Opcode port is usually bound to the trigger port because operations have at least one input. And if you wish to initiate an operation with one input operand, the operand has to be written to the trigger port. Operation codes also have to be declared in HDB.

FUs can also have ports connecting to the external of the TTA processor core. They are declared like any other ports in the entity declaration but these ports must be defined as external in HDB.

See the TCE Tour-tutorial (Section 3.1) for an example how to add an FU implementation to hdb.

1 Operation code order

If there are multiple operations in a Function Unit the operation codes should be numbered according to their alphabetical order. E.g. if there is an ALU with following operations: `Add', `Sub', `And', `Xor' and `Not' the operation codes should be ordered as following:

Operation name Operation code
Add 0
And 1
Not 2
Sub 3
Xor 4

HDBEditor and Processor Generator will issue a warning message if this guideline is not used in operation code numbering. Currently other numbering conventions can still be used but the support might be dropped in future versions of TCE. In order to ensure compatibility it is recommended that you use this new convention.

2 Summary of interface ports

1 Input/Output operand ports

VHDL-type: std_logic_vector
TCE naming convention is to use t1data for the triggering input port and o1data, o2data ... etc. for the rest of input operands. Output port is usually called r1data.

Use generics when you define widths for these ports.

2 Input load ports

VHDL-type: std_logic
The load ports are named after the input operand ports. For example load port of t1data is t1load and o1data is o1load.

3 Operation code port

VHDL-type: std_logic_vector
Operation code port is usually called t1opcode and it is bound to the trigger port.

4 Control signals

VHDL-type: std_logic
There are four control signals available in FUs:

clk is the most obvious, it is the clock signal

rstx is active low reset (x stands for active low)

glock is a Global Lock signal. For example if the global control unit (GCU) issues global lock the ongoing operation should freeze and wait for the global lock signal to become inactive before resuming execution.

glock_r is global lock request. Rarely used in normal function units. It can be used to request global lock state, for example, in case the result does not arrive in the time set by the static latency of the operation.

A common example using this signal is a load-store unit of which memory latency is sometimes larger than the static latency informed to the compiler due to dynamic behavior of the memory system. In that case, a global lock is requested after the static number of cycles has passed and the data has not arrived to the load-store-unit from the memory system.

3 Reserved keywords in generics

Currently there is only one reserved keyword in generic definitions and it is addrw. This keyword is used in load-store units to define trigger port's width according to the data address space width. Processor Generator identifies this keyword and defines the port width from the data address space assigned to the LSU in the ADF.

Pekka Jääskeläinen 2018-03-12