vhdl
                This is an old revision of the document!
Table of Contents
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;
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
vhdl.1761768334.txt.gz · Last modified: 2025/10/29 20:05 by 147.32.8.31
                
                