Site Tools


vhdl

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;
 
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;

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;

Convolution

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;

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

GHDL FLI

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;
#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);
}
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

https://github.com/Paebbels/JSON-for-VHDL

vhdl.txt · Last modified: 2025/10/29 20:27 by 147.32.8.31