[Oberon] What is the status of Lola-2 and its use in the FPGA version of Project Oberon?

Jörg Straube joerg.straube at iaeth.ch
Sat Mar 16 10:33:45 CET 2019


Hi Wojtek

I know my example is not directly comparable to your example but perhaps a little bit...

structural Oberon
. . . . . . . . . . . . . . . .
PROCEDURE Copy(src, dst: ARRAY OF INTEGER);
VAR i: INTEGER;
BEGIN
  i:=0;
  WHILE i < LEN(dst) DO
      dst[i] := src[i]; INC(i)
  END
END Copy;

VAR a, b: ARRAY 30 OF INTEGER;
Copy(a, b);

You see you have to declare a procedure, state the types, declare variables and initialize a lot yourself.

behavioral Oberon
. . . . . . . . . . . . . . . . 
IMPORT S := SYSTEM;
VAR a, b: ARRAY 30 OF INTEGER;
S.COPY(S.ADR(a), S.ADR(b), 30);

Here you say what you want to do (COPY) and the compiler generates itself the whole loop, and optimizes the code by finding a free register for the index i and holding it in a register iso memory.

Another example that comes to my mind is the discussion we had lately in this forum around self programmed and initialzed jump tables (structural) vs using the CASE statement (behavioral) where the compiler itself initializes the jump table and does the housekeeping of calculating the index in the jump table and jumping indirectly...

br
Jörg

> Am 16.03.2019 um 06:12 schrieb Skulski, Wojciech <skulski at pas.rochester.edu>:
> 
> I tried to send a short tutorial text to this list (26 PDF pages) but it did not get through the list. There was an example of behavioral versus structural VHDL on page 19 and 20. So let me copy-paste in order to satisfy Paul's request. The formatting was lost while copy-paste. 
> 
> I will illustrate a shift register. A shift register is an example of a "hardened logic" provided in Xilinx FPGAs. It is not as simple as a flip flop, and not as complex as  a clock manager or wizardry inside the Xilinx I/O pin. 
> 
> Let me start with the structural implementation using a "hardened" library component SRL32E. Note how many details you need to connect, initialize, etc. This implementation gives you a complete control over all the details. The compiler does not need to guess. So this is the "structural RTL" style of coding. I kind of believe that LOLA is meant this way, more or less. 
> 
> ENTITY Delay_Line_L32 IS
> GENERIC (PipeWdt: INTEGER := 14); -- default bit width of the stream
> PORT (
>  CLK : in STD_LOGIC;
>  CE : in STD_LOGIC; -- clock enable
>  prgm : in STD_LOGIC_VECTOR (4 downto 0); -- delay select between 0 to 31
>  din : in STD_LOGIC_VECTOR (PipeWdt-1 downto 0);
>  dout : out STD_LOGIC_VECTOR (PipeWdt-1 downto 0)
> );
> end Delay_Line_L32; -- end of the interface definition
> 
> ARCHITECTURE SRL32 OF Delay_Line_L32 IS BEGIN
> pipe: FOR i IN 0 TO PipeWdt-1 GENERATE
> slice : SRLC32E
> GENERIC MAP (INIT => X"00000000")
> PORT MAP (
>  CLK => CLK, -- Clock input
>  D => din(i), -- SRL data input
>  Q31 => open, -- SRL cascade output pin (connect only to next SRL)
>  A => prgm, -- 5-bit shift depth select input
>  CE => CE, -- Clock enable can freeze the pipe
>  Q => dout(i)); -- SRL data output
> END GENERATE pipe;
> END SRL32; 
> 
> Now the behavioral version (without the CE).  Note that the code is really simple and self explanatory.  The details will be inferred by the compiler. You describe what you want, and the compiler does the rest. You can check in the synthesis report what the compiler really guessed.
> 
> TYPE Tpipe IS ARRAY(PipeLen-1 downto 0) OF
> STD_LOGIC_VECTOR (PipeWdt-1 downto 0);
> SIGNAL pipe: Tpipe;
> 
> -- The "dynamic shift register" should be inferred by synthesis.
> process (CLK) begin
> if rising_edge (CLK) then
> pipe <= pipe(PipeLen-2 DOWNTO 0) & din;
> end if;
> end process;
> dout <= pipe(conv_integer(prgm)); -- select the dynamic length
> 
> --
> Oberon at lists.inf.ethz.ch mailing list for ETH Oberon and related systems
> https://lists.inf.ethz.ch/mailman/listinfo/oberon



More information about the Oberon mailing list