Skip to content

VHDL

This software and all the accompanying files are provided 'as is' and without any warranties expressed or implied including but not limited to implied warranties of merchantability and fitness for a particular purpose. In no event will the author be liable for any damages whatsoever (including without limitation, damages for loss of business profits, business interruption, loss of business information, or any other pecuniary loss) arising out of the use or inability to use this product.

KITT LEDS

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
library ieee ;
use ieee.std_logic_1164.all ;
use ieee.numeric_std.all ;

entity LEDRegister is
    generic (
        WIDTH : integer := 8 ;
        INVERTED : boolean := false 
    ) ;
    port ( 
        clk : in std_logic ;
        reset : in std_logic ;

        LEDs : out std_logic_vector( WIDTH - 1 downto 0 )
    ) ;
end LEDRegister ;

architecture mix of LEDRegister is
    signal iLEDs : std_logic_vector( WIDTH - 1 downto 0 ) := ( 0 => '1', others => '0' ) ;
begin
    process ( clk, reset, iLEDs ) is
        variable count : unsigned( 23 downto 0 ) ;
        constant ONES : unsigned( 7 downto 0 ) := ( others => '1' ) ;
        variable nLEDs : std_logic_vector( WIDTH - 1 downto 0 ) ;
        variable bZERO0, bZERO1, bZERO2, direction : boolean ;
    begin
        if reset = '1' then
            iLEDs <= ( 0 => '1', others => '0' ) ;
            count := ( others => '0' ) ;
            direction := False ;
        elsif rising_edge( clk ) then
            if bZERO2 and bZERO1 and bZERO0 then
                iLEDs <= nLEDs ;
            end if ;
            bZERO0 := count( 7 downto 0 ) = ONES ;
            bZERO1 := count( 15 downto 8 ) = ONES ;
            bZERO2 := count( 21 downto 16 ) = ONES( 5 downto 0 ) ;
            count := count + 1 ;

            if iLEDs( 0 ) = '1' then
                direction := False ;
            elsif iLEDS( WIDTH - 1 ) = '1' then
                direction := True ;
            end if ;
        end if ;

        if direction then
            nLEDs := iLEDs( 0 ) & iLEDs( WIDTH - 1 downto 1 ) ;
        else
            nLEDs := iLEDs( WIDTH - 2 downto 0 ) & iLEDs( WIDTH - 1 ) ;
        end if ;
    end process ;

     g0 : if not INVERTED generate
         LEDs <= iLEDs ;
     end generate ;
     g1 : if INVERTED generate
         LEDs <= not iLEDs ;
     end generate ;
end mix ;

Clip package

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
----------------------------------------------------------------------------------
-- Company: mediatronix
-- Copyright: 2003
----------------------------------------------------------------------------------

library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;

-- takes a variable length vector shortens to the required length, 
-- clipping the value to the (signed) range that fits the new length

package pkg_clip is
  function clip(aIn : signed; len : natural) return signed;
  function clip(aIn : std_logic_vector; len : natural) return signed;
  function clip(aIn : std_logic_vector; len : natural) return std_logic_vector;
  function clip(aIn : signed; len : natural) return std_logic_vector;
end package pkg_clip;

package body pkg_clip is
  -- private
  function and_reduce(ARG : signed) return UX01 is
    variable result         : std_logic;
  begin
    result := '1';
    for i in ARG'range loop
      result := result and ARG(i);
    end loop;
    return result;
  end and_reduce;

  function or_reduce(ARG : signed) return UX01 is
    variable result        : std_logic;
  begin
    result := '0';
    for i in ARG'range loop
      result := result or ARG(i);
    end loop;
    return result;
  end or_reduce;

  -- basic shorten and (signed) clip function
  function clip_base(aIn : signed; len : natural) return signed is
    constant ZEROES    : signed(aIn'length - 1 downto 0) := (others => '0');
    constant ONES      : signed(aIn'length - 1 downto 0) := (others => '1');
    variable temp      : signed(aIn'length - 1 downto 0);
    variable orr, andr : std_logic;
  begin
    temp := aIn; -- (down) shifted version of aIn; aIn could be, say, (31 downto 16)

    orr  := or_reduce(temp(temp'high downto len - 1));  -- unsaturated positive
    andr := and_reduce(temp(temp'high downto len - 1)); -- unsaturated negative

    if orr = '0' or andr = '1' then -- unsaturated positive, or negative?
      return temp(len - 1 downto 0);  -- we can just shorten

    elsif temp(temp'high) = '0' then
      return '0' & ONES(len - 2 downto 0); -- max positive
    else
      return '1' & ZEROES(len - 2 downto 0); -- max negative
    end if;
  end clip_base;

  -- public 
  function clip(aIn : signed; len : natural) return signed is
  begin
    return clip_base(aIn, len);
  end clip;

  function clip(aIn : std_logic_vector; len : natural) return signed is
  begin
    return clip_base(signed(aIn), len);
  end clip;

  function clip(aIn : std_logic_vector; len : natural) return std_logic_vector is
  begin
    return std_logic_vector(clip_base(signed(aIn), len));
  end clip;

  function clip(aIn : signed; len : natural) return std_logic_vector is
  begin
    return std_logic_vector(clip_base(aIn, len));
  end clip;
end package body pkg_clip;

Simple SPI slave

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
----------------------------------------------------------------------------------
-- Company: mediatronix
-- Copyright: 2012
----------------------------------------------------------------------------------

library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.NUMERIC_STD.all;

entity SPI is
  generic (
    WIDTH : integer := 16
  );
  port (
    aclk : in std_logic;

    -- SPI CE events
    fe_tvalid : out std_logic; -- falling edge of CE
    re_tvalid : out std_logic; -- rising edge of CE

    -- put data in the shift register
    s_tvalid : in std_logic;
    s_tdata  : in std_logic_vector(WIDTH - 1 downto 0);

    -- command event, after WIDTH rising sclk edges
    c_tvalid : out std_logic;
    -- data event, after all following WIDTH rising sclk edges
    d_tvalid : out std_logic;
    -- latched command part
    c_tdata : out std_logic_vector(WIDTH - 1 downto 0);

    -- contents of shift register + MOSI
    m_tdata : out std_logic_vector(WIDTH - 1 downto 0);

    sclk : in std_logic;
    ce   : in std_logic;
    miso : out std_logic;
    mosi : in std_logic
  );
end SPI;

-- serial register is WIDTH wide
-- first incoming bits are the command, following is data 

architecture mix of SPI is
  signal sreg      : std_logic_vector(WIDTH - 1 downto 0); -- big endian 16 bit 
  signal cmd_count : unsigned(15 downto 0) := (others => '0');

  signal dce0, dce1 : std_logic := '0';
  signal dck0, dck1 : std_logic := '0';
begin
  process (aclk) is
    variable next_sreg : std_logic_vector(WIDTH - 1 downto 0);
  begin
    if rising_edge(aclk) then
      -- store input data to the top of the shift register, usually at falling edge of CE
      if s_tvalid = '1' then
        sreg <= s_tdata(7 downto 0) & s_tdata(15 downto 8); -- little endian
      end if;

      -- ce synchronizer
      dce1 <= dce0;
      dce0 <= ce;

      -- falling edge CE
      fe_tvalid <= '0';
      if dce0 = '0' and dce1 = '1' then
        fe_tvalid <= '1';
        cmd_count <= (others => '0');

        sreg <= (others => '1'); -- preset sreg with all ones
      end if;

      -- rising edge CE
      re_tvalid <= '0';
      if dce0 = '1' and dce1 = '0' then
        re_tvalid <= '1';
      end if;

      -- sclk synchronizer
      dck1 <= dck0;
      dck0 <= sclk;

      c_tvalid <= '0';
      d_tvalid <= '0';
      next_sreg := sreg(sreg'high - 1 downto sreg'low) & mosi;

      if dck0 = '1' and dck1 = '0' then -- rising edge of SCLK
        -- main shiftregister
        -- shifts sreg left entering mosi at sreg'low
        sreg <= next_sreg;

        -- on the fly processing of incoming commands
        if cmd_count = X"000F" then                                 -- only once
          c_tdata  <= next_sreg(7 downto 0) & next_sreg(15 downto 8); -- little endian
          c_tvalid <= '1';                                            -- and strobes c_tvalid, so user can process cmd
        elsif cmd_count(3 downto 0) = X"F" then                     -- every 16 bits
          m_tdata  <= next_sreg(7 downto 0) & next_sreg(15 downto 8); -- little endian
          d_tvalid <= '1';                                            -- and strobes d_tvalid, so user can process data phase
        end if;

        -- command bits counter
        cmd_count <= cmd_count + 1;
      end if;
    end if;
  end process;

  -- miso out

  miso <= sreg(sreg'high) when ce = '0' else 'Z'; -- miso is the higest bit of the sreg

end architecture mix;

PicoBlaze™ PB2 package

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
library ieee;
use ieee.std_logic_1164.all;

package pb2_pkg is
    -- PB2 bus  
    type t_PB2I is
    record
        ck : std_logic ;
        rs : std_logic ;
        da : std_logic_vector( 7 downto 0 ) ;
        ad : std_logic_vector( 7 downto 0 ) ;
        wr : std_logic ;
        rd : std_logic ;
    end record ;
    type t_PB2O is
    record
        da : std_logic_vector( 7 downto 0 ) ;
        oe : std_logic ;
    end record ;
end pb2_pkg;

package body pb2_pkg is 
end pb2_pkg;

PicoBlaze™ UART

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
library ieee ;
use ieee.std_logic_1164.all ;
use ieee.numeric_std.all ;

use work.pb2_pkg.all ;

entity UART6 is
    generic (
        constant CLOCK : integer := 0 ;
        constant LOC : std_logic_vector ( 7 downto 0 ) := X"00" ;
        constant BAUD : integer := 0
    ) ;
    port ( 
        PB2I : in t_PB2I ;
        PB2O : out t_PB2O ;

        tx : out std_logic ;
        rx : in std_logic
    ) ;
end UART6 ;

architecture mix of UART6 is
    constant UART_CS : std_logic_vector( 3 downto 0 ) := X"C" ;
    constant UART_DA : std_logic_vector( 3 downto 0 ) := X"D" ;

    signal rds, rdd, wr, baudclk : std_logic ;
    signal status : std_logic_vector( 7 downto 0 ) := ( others => '0' ) ;
    signal rxdata : std_logic_vector( 7 downto 0 ) ;
begin
    rds <= PB2I.rd when PB2I.ad( 7 downto 4 ) = LOC( 7 downto 4 ) and PB2I.AD( 3 downto 0 ) = UART_CS else '0' ;
    rdd <= PB2I.rd when PB2I.ad( 7 downto 4 ) = LOC( 7 downto 4 ) and PB2I.AD( 3 downto 0 ) = UART_DA else '0' ;
    wr  <= PB2I.wr when PB2I.ad( 7 downto 4 ) = LOC( 7 downto 4 ) and PB2I.AD( 3 downto 0 ) = UART_DA else '0' ;

    PB2O.oe <= rds or rdd ;

    PB2O.da <= 
        status when rds = '1' else
        rxdata when rdd = '1' else
        ( others => '0' ) ;

    status( 6 ) <= '0' ;    
    status( 7 ) <= '1' when status( 6 downto 0 ) /= "0000000" else '0' ;    

    process ( PB2I.ck, PB2I.rs ) is
        variable count, ncount : integer ;
        variable bZERO : boolean ;
    begin
        if PB2I.rs = '1' then
            baudclk <= '0' ;
        elsif rising_edge( PB2I.ck ) then
            bZERO := count < 0 ;
            ncount := count - BAUD * 16 ;
            baudclk <= '0' ;
            if bZERO then
                baudclk <= '1' ;
                ncount := count + CLOCK - BAUD * 16 ;
            end if ;
            count := ncount ;
            end if ;
    end process ;

    recv : entity work.uart_rx6( low_level_definition )
        port map (
            serial_in => rx,    

            data_out => rxdata,                                
            buffer_read => rdd,                                
            buffer_reset => PB2I.rs,                               
            en_16_x_baud => baudclk,   

            buffer_data_present => status( 5 ),                
            buffer_full => status( 4 ),                        
            buffer_half_full => status( 3 ), 

            clk => PB2I.ck                                         
        ) ;

    xmit : entity work.uart_tx6( low_level_definition )
        port map (
            data_in => PB2I.da,                         
            buffer_write => wr,                    
            buffer_reset => PB2I.rs,                   
            en_16_x_baud => baudclk,  

            serial_out => tx,                      

            buffer_data_present => status( 2 ),    
            buffer_full => status( 0 ),            
            buffer_half_full => status( 1 ), 

            clk => PB2I.ck                             
        ) ;                                        

end mix ;

Rijndael/AES-128 SBOX

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
-- AES SBOX as a PicoBlaze™ I/O device
-- occupies 1 byte in the address map.
-- witing a value sets the address pointer of the ROM
-- reading reads the byte pointed at by the address

library ieee ;
use ieee.std_logic_1164.all ; 
use ieee.numeric_std.all ; 

use work.pb2_pkg.all ;

entity SBOX is
    generic (
        constant LOC : std_logic_vector ( 7 downto 0 ) := X"00"
    ) ;
    port ( 
        PB2I : in t_PB2I ;
        PB2O : out t_PB2O
    ) ;
end SBOX ;

architecture mix of SBOX is
    type ROM_t is array( 0 to 255 ) of std_logic_vector( 7 downto 0 ) ; 
    signal rom : ROM_t := ( 
            0   => X"63", 1   => X"7C", 2   => X"77", 3   => X"7B", 4   => X"F2", 5   => X"6B", 6   => X"6F", 7   => X"C5", 
            8   => X"30", 9   => X"01", 10  => X"67", 11  => X"2B", 12  => X"FE", 13  => X"D7", 14  => X"AB", 15  => X"76", 
            16  => X"CA", 17  => X"82", 18  => X"C9", 19  => X"7D", 20  => X"FA", 21  => X"59", 22  => X"47", 23  => X"F0", 
            24  => X"AD", 25  => X"D4", 26  => X"A2", 27  => X"AF", 28  => X"9C", 29  => X"A4", 30  => X"72", 31  => X"C0", 
            32  => X"B7", 33  => X"FD", 34  => X"93", 35  => X"26", 36  => X"36", 37  => X"3F", 38  => X"F7", 39  => X"CC", 
            40  => X"34", 41  => X"A5", 42  => X"E5", 43  => X"F1", 44  => X"71", 45  => X"D8", 46  => X"31", 47  => X"15", 
            48  => X"04", 49  => X"C7", 50  => X"23", 51  => X"C3", 52  => X"18", 53  => X"96", 54  => X"05", 55  => X"9A", 
            56  => X"07", 57  => X"12", 58  => X"80", 59  => X"E2", 60  => X"EB", 61  => X"27", 62  => X"B2", 63  => X"75", 
            64  => X"09", 65  => X"83", 66  => X"2C", 67  => X"1A", 68  => X"1B", 69  => X"6E", 70  => X"5A", 71  => X"A0", 
            72  => X"52", 73  => X"3B", 74  => X"D6", 75  => X"B3", 76  => X"29", 77  => X"E3", 78  => X"2F", 79  => X"84", 
            80  => X"53", 81  => X"D1", 83  => X"ED", 84  => X"20", 85  => X"FC", 86  => X"B1", 87  => X"5B", 88  => X"6A", 
            89  => X"CB", 90  => X"BE", 91  => X"39", 92  => X"4A", 93  => X"4C", 94  => X"58", 95  => X"CF", 96  => X"D0", 
            97  => X"EF", 98  => X"AA", 99  => X"FB", 100 => X"43", 101 => X"4D", 102 => X"33", 103 => X"85", 104 => X"45", 
            105 => X"F9", 106 => X"02", 107 => X"7F", 108 => X"50", 109 => X"3C", 110 => X"9F", 111 => X"A8", 112 => X"51", 
            113 => X"A3", 114 => X"40", 115 => X"8F", 116 => X"92", 117 => X"9D", 118 => X"38", 119 => X"F5", 120 => X"BC", 
            121 => X"B6", 122 => X"DA", 123 => X"21", 124 => X"10", 125 => X"FF", 126 => X"F3", 127 => X"D2", 128 => X"CD", 
            129 => X"0C", 130 => X"13", 131 => X"EC", 132 => X"5F", 133 => X"97", 134 => X"44", 135 => X"17", 136 => X"C4", 
            137 => X"A7", 138 => X"7E", 139 => X"3D", 140 => X"64", 141 => X"5D", 142 => X"19", 143 => X"73", 144 => X"60", 
            145 => X"81", 146 => X"4F", 147 => X"DC", 148 => X"22", 149 => X"2A", 150 => X"90", 151 => X"88", 152 => X"46", 
            153 => X"EE", 154 => X"B8", 155 => X"14", 156 => X"DE", 157 => X"5E", 158 => X"0B", 159 => X"DB", 160 => X"E0", 
            161 => X"32", 162 => X"3A", 163 => X"0A", 164 => X"49", 165 => X"06", 166 => X"24", 167 => X"5C", 168 => X"C2", 
            169 => X"D3", 170 => X"AC", 171 => X"62", 172 => X"91", 173 => X"95", 174 => X"E4", 175 => X"79", 176 => X"E7", 
            177 => X"C8", 178 => X"37", 179 => X"6D", 180 => X"8D", 181 => X"D5", 182 => X"4E", 183 => X"A9", 184 => X"6C", 
            185 => X"56", 186 => X"F4", 187 => X"EA", 188 => X"65", 189 => X"7A", 190 => X"AE", 191 => X"08", 192 => X"BA", 
            193 => X"78", 194 => X"25", 195 => X"2E", 196 => X"1C", 197 => X"A6", 198 => X"B4", 199 => X"C6", 200 => X"E8", 
            201 => X"DD", 202 => X"74", 203 => X"1F", 204 => X"4B", 205 => X"BD", 206 => X"8B", 207 => X"8A", 208 => X"70", 
            209 => X"3E", 210 => X"B5", 211 => X"66", 212 => X"48", 213 => X"03", 214 => X"F6", 215 => X"0E", 216 => X"61", 
            217 => X"35", 218 => X"57", 219 => X"B9", 220 => X"86", 221 => X"C1", 222 => X"1D", 223 => X"9E", 224 => X"E1", 
            225 => X"F8", 226 => X"98", 227 => X"11", 228 => X"69", 229 => X"D9", 230 => X"8E", 231 => X"94", 232 => X"9B", 
            233 => X"1E", 234 => X"87", 235 => X"E9", 236 => X"CE", 237 => X"55", 238 => X"28", 239 => X"DF", 240 => X"8C", 
            241 => X"A1", 242 => X"89", 243 => X"0D", 244 => X"BF", 245 => X"E6", 246 => X"42", 247 => X"68", 248 => X"41", 
            249 => X"99", 250 => X"2D", 251 => X"0F", 252 => X"B0", 253 => X"54", 254 => X"BB", 255 => X"16", 
            others => X"00" 
    ) ;
    signal rd, wr : std_logic ;
    signal addr : std_logic_vector( 7 downto 0 ) ;
begin 
    rd <= PB2I.rd when PB2I.ad = LOC else '0' ;
    wr <= PB2I.wr when PB2I.ad = LOC else '0' ;

    PB2O.oe <= rd ;

    PB2O.da <= 
        rom( to_integer( unsigned( addr ) ) ) when rd = '1' else
        ( others => '0' ) ;

    process ( PB2I.rs, PB2I.ck ) is
    begin
        if PB2I.rs = '1' then
            addr <= ( others => '0' ) ;
        elsif rising_edge( PB2I.ck ) then
            if wr = '1' then
                addr <= PB2I.da ;
            end if ;
        end if ;
    end process ;
end mix ;