Site Tools


vhdl

This is an old revision of the document!


VHDL

https://www.mouser.com/datasheet/2/598/DE25_Standard_User_manual_revC-3680989.pdf

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
 
entity Conv2D is
    generic (
        KERNEL_SIZE : integer := 3;    -- e.g., 3x3 kernel
        IMG_SIZE    : integer := 8;    -- Input image size (e.g., 8x8)
        -- Kernel weights (example: simple edge detection)
        -- For real use, replace with learned weights from ONNX model
        -- For 3x3 kernel
        kernel_weights : array (0 to KERNEL_SIZE-1, 0 to KERNEL_SIZE-1) of signed(7 downto 0) := (
            (to_signed(-1,8), to_signed(-1,8), to_signed(-1,8)),
            (to_signed(-1,8), to_signed(8,8),  to_signed(-1,8)),
            (to_signed(-1,8), to_signed(-1,8), to_signed(-1,8))
        )
    );
    port (
        clk       : in std_logic;
        reset     : in std_logic;
        input_pixel  : in std_logic_vector(7 downto 0);
        -- For simplicity, assuming streaming input pixel by pixel
        -- Implement line buffers to handle 2D windowing
        -- Output
        conv_out  : out std_logic_vector(15 downto 0)
    );
end Conv2D;
 
architecture Behavioral of Conv2D is
 
    -- Line buffers to store previous rows
    type line_buffer_type is array (0 to KERNEL_SIZE-2, 0 to IMG_SIZE-1) of signed(7 downto 0);
    signal line_buffer : line_buffer_type;
 
    -- Window buffer to hold current KxK pixels
    type window_type is array (0 to KERNEL_SIZE-1, 0 to KERNEL_SIZE-1) of signed(7 downto 0);
    signal window : window_type;
 
    -- Counters to track position
    signal row_cnt, col_cnt : integer range 0 to IMG_SIZE-1 := 0;
 
begin
 
    process(clk, reset)
    begin
        if reset = '1' then
            row_cnt <= 0;
            col_cnt <= 0;
            -- Initialize buffers if needed
        elsif rising_edge(clk) then
            -- Shift input pixel into line buffers
            -- Update line buffers
            for i in 0 to KERNEL_SIZE-2 loop
                line_buffer(i, col_cnt) <= line_buffer(i+1, col_cnt);
            end loop;
            if row_cnt = 0 then
                -- First row, no previous data
                line_buffer(0, col_cnt) <= signed(input_pixel);
            else
                line_buffer(0, col_cnt) <= signed(input_pixel);
            end if;
 
            -- Fill window
            if row_cnt >= KERNEL_SIZE-1 and col_cnt >= KERNEL_SIZE-1 then
                -- Collect window pixels
                for i in 0 to KERNEL_SIZE-1 loop
                    for j in 0 to KERNEL_SIZE-1 loop
                        if i = KERNEL_SIZE-1 and j = KERNEL_SIZE-1 then
                            -- current pixel
                            window(i,j) <= signed(input_pixel);
                        elsif i = KERNEL_SIZE-1 then
                            -- same row, from line buffer
                            window(i,j) <= line_buffer(i-1, col_cnt - (KERNEL_SIZE - 1 - j));
                        elsif j = KERNEL_SIZE-1 then
                            -- from previous line buffer
                            window(i,j) <= line_buffer(i-1, col_cnt - (KERNEL_SIZE - 1 - j));
                        else
                            -- For simplicity, assume all data is available
                            -- In practice, implement proper line buffering
                        end if;
                    end loop;
                end loop;
 
                -- Perform convolution
                variable sum : signed(15 downto 0) := (others => '0');
                for i in 0 to KERNEL_SIZE-1 loop
                    for j in 0 to KERNEL_SIZE-1 loop
                        sum := sum + resize(window(i,j), 16) * resize(kernel_weights(i,j), 16);
                    end loop;
                end loop;
 
                conv_out <= std_logic_vector(sum);
            end if;
 
            -- Update column counter
            if col_cnt = IMG_SIZE - 1 then
                col_cnt <= 0;
                if row_cnt = IMG_SIZE - 1 then
                    row_cnt <= 0;
                else
                    row_cnt <= row_cnt + 1;
                end if;
            else
                col_cnt <= col_cnt + 1;
            end if;
        end if;
    end process;
end Behavioral;

DDR Memory

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
 
entity DDR_Read_Write is
    port (
        clk           : in std_logic;            -- System clock
        reset_n       : in std_logic;            -- Active low reset
        -- DDR controller interface signals
        -- These are placeholder signals; replace with your DDR controller's interface
        ddr_addr      : out std_logic_vector(31 downto 0);
        ddr_dq        : inout std_logic_vector(63 downto 0); -- Data bus
        ddr_dqs       : inout std_logic_vector(7 downto 0);
        ddr_we_n      : out std_logic;
        ddr_oe_n      : out std_logic;
        ddr_cs_n      : out std_logic;
        -- Control signals for read/write
        start_write   : in std_logic;
        start_read    : in std_logic;
        write_data    : in std_logic_vector(63 downto 0);
        read_data     : out std_logic_vector(63 downto 0);
        write_done    : out std_logic;
        read_done     : out std_logic
    );
end entity;
 
architecture Behavioral of DDR_Read_Write is
 
    type state_type is (IDLE, WRITE, READ, DONE);
    signal state : state_type := IDLE;
 
    signal addr_reg : std_logic_vector(31 downto 0) := (others => '0');
    signal data_reg : std_logic_vector(63 downto 0) := (others => '0');
 
begin
 
    process(clk, reset_n)
    begin
        if reset_n = '0' then
            state <= IDLE;
            ddr_we_n <= '1';
            ddr_oe_n <= '1';
            ddr_cs_n <= '1';
            write_done <= '0';
            read_done <= '0';
            read_data <= (others => '0');
            addr_reg <= (others => '0');
        elsif rising_edge(clk) then
            case state is
                when IDLE =>
                    write_done <= '0';
                    read_done <= '0';
                    if start_write = '1' then
                        addr_reg <= (others => '0'); -- Set your address here
                        data_reg <= write_data;
                        state <= WRITE;
                    elsif start_read = '1' then
                        addr_reg <= (others => '0'); -- Set your address here
                        state <= READ;
                    end if;
 
                when WRITE =>
                    -- Drive DDR signals for write
                    ddr_addr <= addr_reg;
                    ddr_dq <= data_reg;
                    ddr_we_n <= '0'; -- Assert write enable
                    ddr_oe_n <= '1'; -- Disable output during write
                    ddr_cs_n <= '0'; -- Chip select active
                    -- Add necessary timing delays as per DDR spec
                    -- For simplicity, assume one cycle write
                    write_done <= '1';
                    ddr_we_n <= '1'; -- Deassert write enable
                    ddr_cs_n <= '1';
                    state <= IDLE;
 
                when READ =>
                    -- Drive DDR signals for read
                    ddr_addr <= addr_reg;
                    ddr_we_n <= '1';
                    ddr_oe_n <= '0'; -- Enable output
                    ddr_cs_n <= '0';
                    -- Wait for data to be valid (depends on DDR timing)
                    -- For simplicity, assume data is ready immediately
                    read_data <= ddr_dq;
                    read_done <= '1';
                    ddr_oe_n <= '1';
                    ddr_cs_n <= '1';
                    state <= IDLE;
 
                when others =>
                    state <= IDLE;
            end case;
        end if;
    end process;
 
end architecture;

SDRAM Memory

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
 
entity sdram_controller is
    port (
        clk          : in  std_logic;
        reset        : in  std_logic;
        -- Control signals
        wr_enable    : in  std_logic; -- Write enable
        rd_enable    : in  std_logic; -- Read enable
        address      : in  std_logic_vector(23 downto 0); -- Address bus
        write_data   : in  std_logic_vector(15 downto 0); -- Data to write
        read_data    : out std_logic_vector(15 downto 0); -- Data read from SDRAM
        read_valid   : out std_logic; -- Indicates valid read data
        -- SDRAM interface signals (simplified)
        sdram_dq     : inout std_logic_vector(15 downto 0);
        sdram_addr   : out std_logic_vector(12 downto 0);
        sdram_ba     : out std_logic_vector(1 downto 0);
        sdram_cs_n   : out std_logic;
        sdram_ras_n  : out std_logic;
        sdram_cas_n  : out std_logic;
        sdram_we_n   : out std_logic
    );
end entity;
 
===== DDR Memory =====
 
architecture Behavioral of sdram_controller is
 
    type state_type is (
        IDLE,
        PRECHARGE,
        ACTIVATE,
        WRITE,
        READ,
        PRECHARGE_AFTER,
        WAIT
    );
    signal state       : state_type := IDLE;
    signal next_state  : state_type;
 
    -- Internal signals
    signal row_address : std_logic_vector(12 downto 0);
    signal col_address : std_logic_vector(9 downto 0);
    signal data_out    : std_logic_vector(15 downto 0);
    signal data_in     : std_logic_vector(15 downto 0);
    signal data_valid  : std_logic := '0';
 
    -- Timing counters (simplified)
    signal wait_counter : integer := 0;
 
begin
 
    process(clk, reset)
    begin
        if reset = '1' then
            state <= IDLE;
            sdram_cs_n <= '1';
            sdram_ras_n <= '1';
            sdram_cas_n <= '1';
            sdram_we_n <= '1';
            sdram_addr <= (others => '0');
            sdram_ba <= (others => '0');
            read_data <= (others => '0');
            read_valid <= '0';
            wait_counter <= 0;
        elsif rising_edge(clk) then
            case state is
                when IDLE =>
                    read_valid <= '0';
                    if wr_enable = '1' then
                        -- Initiate write sequence
                        sdram_cs_n <= '0';
                        sdram_ras_n <= '0';
                        sdram_cas_n <= '1';
                        sdram_we_n <= '0'; -- Write command
                        sdram_addr <= address(12 downto 0); -- Column address
                        sdram_ba <= "00"; -- Bank address, adapt as needed
                        state <= PRECHARGE;
                        wait_counter <= 2; -- Wait cycles for command
                        data_out <= write_data;
                    elsif rd_enable = '1' then
                        -- Initiate read sequence
                        sdram_cs_n <= '0';
                        sdram_ras_n <= '0';
                        sdram_cas_n <= '0'; -- Read command
                        sdram_we_n <= '1';
                        sdram_addr <= address(12 downto 0);
                        sdram_ba <= "00"; -- Bank address
                        state <= PRECHARGE;
                        wait_counter <= 2; -- Wait cycles for command
                    end if;
 
                when PRECHARGE =>
                    if wait_counter > 0 then
                        wait_counter <= wait_counter - 1;
                    else
                        -- Activate row
                        sdram_ras_n <= '0';
                        sdram_cas_n <= '1';
                        sdram_we_n <= '1';
                        sdram_addr <= address(23 downto 11); -- Row address
                        state <= ACTIVATE;
                        wait_counter <= 2;
                    end if;
 
                when ACTIVATE =>
                    if wait_counter > 0 then
                        wait_counter <= wait_counter - 1;
                    else
                        if wr_enable = '1' then
                            -- Issue write command
                            sdram_ras_n <= '1';
                            sdram_cas_n <= '0';
                            sdram_we_n <= '0';
                            sdram_addr <= address(12 downto 0); -- Column address
                            state <= WRITE;
                            wait_counter <= 2;
                        elsif rd_enable = '1' then
                            -- Issue read command
                            sdram_ras_n <= '1';
                            sdram_cas_n <= '0';
                            sdram_we_n <= '1';
                            sdram_addr <= address(12 downto 0); -- Column address
                            state <= READ;
                            wait_counter <= 2;
                        end if;
                    end if;
 
                when WRITE =>
                    if wait_counter > 0 then
                        wait_counter <= wait_counter - 1;
                        sdram_dq <= data_out;
                    else
                        -- Finish write
                        sdram_cs_n <= '1';
                        sdram_ras_n <= '1';
                        sdram_cas_n <= '1';
                        sdram_we_n <= '1';
                        state <= WAIT;
                        wait_counter <= 2; -- Wait before next command
                    end if;
 
                when READ =>
                    if wait_counter > 0 then
                        wait_counter <= wait_counter - 1;
                    else
                        -- Read data (assuming data is valid after tRCD)
                        read_data <= sdram_dq;
                        read_valid <= '1';
                        sdram_cs_n <= '1';
                        sdram_ras_n <= '1';
                        sdram_cas_n <= '1';
                        sdram_we_n <= '1';
                        state <= WAIT;
                        wait_counter <= 2;
                    end if;
 
                when WAIT =>
                    if wait_counter > 0 then
                        wait_counter <= wait_counter - 1;
                    else
                        state <= IDLE; -- Ready for next operation
                    end if;
 
                when others =>
                    state <= IDLE;
            end case;
        end if;
    end process;
 
end Behavioral;

ghdl memory

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
 
entity ram is
    generic (
        DATA_WIDTH : integer := 8;  -- Width of data bus
        ADDR_WIDTH : integer := 4   -- Width of address bus (16 addresses)
    );
    port (
        clk      : in std_logic;
        we       : in std_logic; -- Write enable
        addr     : in std_logic_vector(ADDR_WIDTH-1 downto 0);
        data_in  : in std_logic_vector(DATA_WIDTH-1 downto 0);
        data_out : out std_logic_vector(DATA_WIDTH-1 downto 0)
    );
end entity;
 
architecture Behavioral of ram is
    type mem_type is array (0 to 2**ADDR_WIDTH - 1) of std_logic_vector(DATA_WIDTH-1 downto 0);
    signal mem : mem_type := (others => (others => '0'));
begin
    process(clk)
    begin
        if rising_edge(clk) then
            if we = '1' then
                -- Write operation
                mem(to_integer(unsigned(addr))) <= data_in;
            end if;
            -- Read operation
            data_out <= mem(to_integer(unsigned(addr)));
        end if;
    end process;
end architecture;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
 
entity tb_ram is
end entity;
 
architecture Behavioral of tb_ram is
    signal clk      : std_logic := '0';
    signal we       : std_logic := '0';
    signal addr     : std_logic_vector(3 downto 0);
    signal data_in  : std_logic_vector(7 downto 0);
    signal data_out : std_logic_vector(7 downto 0);
 
    component ram
        generic (
            DATA_WIDTH : integer := 8;
            ADDR_WIDTH : integer := 4
        );
        port (
            clk      : in std_logic;
            we       : in std_logic;
            addr     : in std_logic_vector(ADDR_WIDTH-1 downto 0);
            data_in  : in std_logic_vector(DATA_WIDTH-1 downto 0);
            data_out : out std_logic_vector(DATA_WIDTH-1 downto 0)
        );
    end component;
begin
    uut: ram
        port map (
            clk => clk,
            we => we,
            addr => addr,
            data_in => data_in,
            data_out => data_out
        );
 
    -- Clock generation
    clk_process : process
    begin
        while true loop
            clk <= '0';
            wait for 10 ns;
            clk <= '1';
            wait for 10 ns;
        end loop;
    end process;
 
    -- Test sequence
    stim_proc: process
    begin
        -- Write data to address 0x1
        addr <= "0001";
        data_in <= "10101010";
        we <= '1';
        wait for 20 ns;
 
        -- Disable write
        we <= '0';
        wait for 20 ns;
 
        -- Read from address 0x1
        addr <= "0001";
        wait for 20 ns;
 
        -- Write data to address 0x2
        addr <= "0010";
        data_in <= "11001100";
        we <= '1';
        wait for 20 ns;
 
        -- Disable write
        we <= '0';
        wait for 20 ns;
 
        -- Read from address 0x2
        addr <= "0010";
        wait for 20 ns;
 
        wait;
    end process;
end architecture;
Compile:            ghdl -a ram.vhd tb_ram.vhd
Elaborate:          ghdl -e tb_ram
Run the simulation: ghdl -r tb_ram --wave=wave.ghw
View waveform:      gtkwave wave.ghw

Matrix Multiply

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
 
entity MatrixMultiplier is
    port (
        clk       : in std_logic;
        reset     : in std_logic;
        start     : in std_logic;
        done      : out std_logic
        -- Optional: ports for memory interface
    );
end entity;
 
architecture Behavioral of MatrixMultiplier is
 
    -- Define matrix size
    constant N : integer := 2;
 
    -- Define data type
    subtype data_t is signed(15 downto 0); -- 16-bit signed numbers
 
    -- Define matrices stored in memory (arrays)
    type matrix_t is array (0 to N-1, 0 to N-1) of data_t;
 
    -- Initialize matrices A and B
    signal A : matrix_t := (
        (to_signed(1,16), to_signed(2,16)),
        (to_signed(3,16), to_signed(4,16))
    );
 
    signal B : matrix_t := (
        (to_signed(5,16), to_signed(6,16)),
        (to_signed(7,16), to_signed(8,16))
    );
 
    -- Result matrix C
    signal C : matrix_t := (
        (others => (others => '0'))
    );
 
    -- Loop counters
    signal i, j, k : integer range 0 to N-1 := 0;
 
    -- Accumulator for sum
    signal sum : data_t := (others => '0');
 
    -- State machine states
    type state_type is (IDLE, COMPUTE, DONE);
    signal state : state_type := IDLE;
 
begin
 
    process(clk, reset)
    begin
        if reset = '1' then
            -- Reset all signals
            i <= 0;
            j <= 0;
            k <= 0;
            sum <= (others => '0');
            C <= (others => (others => '0'));
            state <= IDLE;
            done <= '0';
 
        elsif rising_edge(clk) then
            case state is
                when IDLE =>
                    if start = '1' then
                        -- Initialize counters
                        i <= 0;
                        j <= 0;
                        k <= 0;
                        sum <= (others => '0');
                        state <= COMPUTE;
                        done <= '0';
                    end if;
 
                when COMPUTE =>
                    -- Perform multiplication: sum += A[i][k] * B[k][j]
                    sum <= sum + A(i,k) * B(k,j);
 
                    if k = N-1 then
                        -- Store result in C[i][j]
                        C(i,j) <= sum;
                        -- Reset sum for next element
                        sum <= (others => '0');
 
                        -- Move to next column
                        if j < N-1 then
                            j <= j + 1;
                            k <= 0;
                        else
                            -- Move to next row
                            j <= 0;
                            if i < N-1 then
                                i <= i + 1;
                                k <= 0;
                            else
                                -- Computation done
                                state <= DONE;
                            end if;
                        end if;
                    else
                        -- Continue summing
                        k <= k + 1;
                    end if;
 
                when DONE =>
                    done <= '1';
                    -- Optionally, stay here or reset
            end case;
        end if;
    end process;
 
end architecture;
vhdl.1761767604.txt.gz · Last modified: 2025/10/29 19:53 by 147.32.8.31