Site Tools


vhdl

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Next revision
Previous revision
vhdl [2025/10/29 19:44] – created 147.32.8.31vhdl [2025/10/29 20:27] (current) – [SDRAM Memory] 147.32.8.31
Line 1: Line 1:
 ==== VHDL ==== ==== VHDL ====
 +
 +https://www.mouser.com/datasheet/2/598/DE25_Standard_User_manual_revC-3680989.pdf
 +
 +<code vhdl>
 +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;
 +</code>
 +
 +===== DDR Memory =====
 +
 +<code vhdl>
 +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;
 +</code>
 +
 +===== SDRAM Memory =====
 +
 +<code vhdl>
 +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;
 +
 +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;
 +</code>
 +
 +==== Matrix Multiply =====
 +
 +<code vhdl>
 +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;
 +</code>
 +
 +
 +==== Convolution ====
 +
 +<code vhdl>
 +library ieee;
 +use ieee.std_logic_1164.all;
 +use ieee.numeric_std.all;
 +
 +entity convolution_kernel is
 +    Port (
 +        clk         : in std_logic;
 +        reset       : in std_logic;
 +        start       : in std_logic;
 +        -- Memory interface
 +        pixel_mem_addr  : out unsigned(15 downto 0); -- Address for pixel memory
 +        pixel_mem_data  : in  unsigned(7 downto 0);  -- Pixel data (e.g., grayscale 8-bit)
 +        pixel_mem_we    : out std_logic;             -- Write enable if needed
 +        -- Output
 +        conv_pixel_out  : out unsigned(7 downto 0);
 +        done            : out std_logic
 +    );
 +end entity;
 +
 +architecture Behavioral of convolution_kernel is
 +
 +    -- Define kernel size
 +    constant KERNEL_SIZE : integer := 3;
 +    constant IMG_WIDTH   : integer := 256; -- Example image width
 +    constant IMG_HEIGHT  : integer := 256; -- Example image height
 +
 +    -- Convolution kernel (e.g., sharpening kernel)
 +    type kernel_type is array (0 to KERNEL_SIZE-1, 0 to KERNEL_SIZE-1) of integer;
 +    constant kernel : kernel_type := (
 +        (0, -1, 0),
 +        (-1, 5, -1),
 +        (0, -1, 0)
 +    );
 +
 +    -- State machine states
 +    type state_type is (IDLE, READ_PIXELS, APPLY_CONV, WRITE_RESULT, DONE);
 +    signal state : state_type := IDLE;
 +
 +    -- Memory address counters
 +    signal x, y : integer range 0 to IMG_WIDTH-1 := 0;
 +    signal pixel_window : array (0 to KERNEL_SIZE-1, 0 to KERNEL_SIZE-1) of unsigned(7 downto 0);
 +    signal pixel_sum : integer := 0;
 +    signal conv_result : unsigned(7 downto 0) := (others => '0');
 +
 +    -- Internal counters
 +    signal row, col : integer range 0 to IMG_HEIGHT-1 := 0;
 +
 +    -- Helper signals
 +    signal pixel_fetch_count : integer range 0 to KERNEL_SIZE*KERNEL_SIZE := 0;
 +
 +begin
 +
 +    process(clk, reset)
 +    begin
 +        if reset = '1' then
 +            state <= IDLE;
 +            pixel_mem_addr <= (others => '0');
 +            pixel_mem_we <= '0';
 +            conv_pixel_out <= (others => '0');
 +            done <= '0';
 +            x <= 0;
 +            y <= 0;
 +            row <= 0;
 +            col <= 0;
 +        elsif rising_edge(clk) then
 +            case state is
 +                when IDLE =>
 +                    if start = '1' then
 +                        x <= 1; -- Start from pixel (1,1) to avoid border issues
 +                        y <= 1;
 +                        row <= 1;
 +                        col <= 1;
 +                        state <= READ_PIXELS;
 +                        pixel_fetch_count <= 0;
 +                    end if;
 +
 +                when READ_PIXELS =>
 +                    -- Read 3x3 neighborhood
 +                    -- Calculate memory address for each pixel in the window
 +                    -- For simplicity, assume row-major order and no boundary checks
 +                    -- In practice, boundary conditions should be handled
 +                    variable addr_x, addr_y : integer;
 +                    variable addr : unsigned(15 downto 0);
 +                    begin
 +                        for i in 0 to KERNEL_SIZE-1 loop
 +                            for j in 0 to KERNEL_SIZE-1 loop
 +                                addr_x := x + j - 1 + i - 1;
 +                                addr_y := y + j - 1;
 +                                -- Boundary check
 +                                if addr_x < 0 then
 +                                    addr_x := 0;
 +                                elsif addr_x >= IMG_WIDTH then
 +                                    addr_x := IMG_WIDTH - 1;
 +                                end if;
 +                                if addr_y < 0 then
 +                                    addr_y := 0;
 +                                elsif addr_y >= IMG_HEIGHT then
 +                                    addr_y := IMG_HEIGHT - 1;
 +                                end if;
 +                                addr := to_unsigned(addr_y * IMG_WIDTH + addr_x, 16);
 +                                pixel_mem_addr <= addr;
 +                                wait for clk'period; -- Wait for memory read
 +                                pixel_window(i, j) <= pixel_mem_data;
 +                            end loop;
 +                        end loop;
 +                        state <= APPLY_CONV;
 +                    end;
 +
 +                when APPLY_CONV =>
 +                    -- Apply convolution
 +                    pixel_sum <= 0;
 +                    for i in 0 to KERNEL_SIZE-1 loop
 +                        for j in 0 to KERNEL_SIZE-1 loop
 +                            pixel_sum <= pixel_sum + kernel(i, j) * to_integer(pixel_window(i, j));
 +                        end loop;
 +                    end loop;
 +
 +                    -- Clamp the result to 0-255
 +                    if pixel_sum < 0 then
 +                        conv_result <= (others => '0');
 +                    elsif pixel_sum > 255 then
 +                        conv_result <= (others => '1');
 +                    else
 +                        conv_result <= to_unsigned(pixel_sum, 8);
 +                    end if;
 +
 +                    state <= WRITE_RESULT;
 +
 +                when WRITE_RESULT =>
 +                    -- Write the convolved pixel back to memory or output
 +                    -- For simplicity, output directly
 +                    conv_pixel_out <= conv_result;
 +
 +                    -- Move to next pixel
 +                    if x < IMG_WIDTH - 2 then
 +                        x <= x + 1;
 +                    else
 +                        x <= 1;
 +                        if y < IMG_HEIGHT - 2 then
 +                            y <= y + 1;
 +                        else
 +                            state <= DONE;
 +                            done <= '1';
 +                        end if;
 +                    end if;
 +                    state <= IDLE;
 +
 +                when DONE =>
 +                    -- Processing complete
 +                    null;
 +
 +                when others =>
 +                    null;
 +            end case;
 +        end if;
 +    end process;
 +
 +end Behavioral;
 +</code>
 +
 +==== ghdl memory ====
 +
 +<code vhdl>
 +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;
 +</code>
 +
 +<code vhdl>
 +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;
 +</code>
 +
 +<code>
 +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
 +</code>
 +
 +
 +==== GHDL FLI ====
 +
 +<code vhdl>
 +library ieee;
 +use ieee.std_logic_1164.all;
 +
 +entity testbench is
 +end entity;
 +
 +architecture sim of testbench is
 +    -- Declare external procedure
 +    procedure external_procedure(signal_value : inout std_logic_vector(7 downto 0));
 +    -- Import the procedure from C
 +    attribute foreign of external_procedure : procedure is "ghdl_fli_example";
 +
 +    signal data : std_logic_vector(7 downto 0) := (others => '0');
 +begin
 +    process
 +    begin
 +        wait for 10 ns;
 +        external_procedure(data);
 +        wait;
 +    end process;
 +end architecture;
 +</code>
 +
 +<code c>
 +#include <stdio.h>
 +#include "ghdl_fli.h"  // GHDL FLI header
 +
 +// This function will be called from VHDL
 +void ghdl_fli_example (void *args) {
 +    // args points to the signal
 +    // For simplicity, assume args is a pointer to an array of 8 chars
 +    unsigned char *signal_value = (unsigned char *) args;
 +
 +    printf("C: Received signal value: 0x%02X", *signal_value);
 +
 +    // Modify the signal (e.g., increment)
 +    *signal_value = (*signal_value + 1) & 0xFF;
 +
 +    printf("C: Modified signal value to: 0x%02X", *signal_value);
 +}
 +</code>
 +
 +<code>
 +gcc -shared -fPIC -o ghdl_fli_example.so ghdl_fli_example.c
 +ghdl -a testbench.vhd
 +ghdl -Wl,ghdl_fli_example.so -e testbench
 +ghdl -r testbench --stop-time=50ns
 +</code>
 +
 +https://github.com/Paebbels/JSON-for-VHDL
 +
vhdl.1761767079.txt.gz · Last modified: 2025/10/29 19:44 by 147.32.8.31