vhdl
                Differences
This shows you the differences between two versions of the page.
| Next revision | Previous revision | ||
| vhdl [2025/10/29 19:44] – created 147.32.8.31 | vhdl [2025/10/29 20:27] (current) – [SDRAM Memory] 147.32.8.31 | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| ==== VHDL ==== | ==== VHDL ==== | ||
| + | |||
| + | https:// | ||
| + | |||
| + | <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 | ||
| + | -- 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, | ||
| + | (to_signed(-1, | ||
| + | (to_signed(-1, | ||
| + | (to_signed(-1, | ||
| + | ) | ||
| + | ); | ||
| + | port ( | ||
| + | clk : in std_logic; | ||
| + | reset : in std_logic; | ||
| + | input_pixel | ||
| + | -- For simplicity, assuming streaming input pixel by pixel | ||
| + | -- Implement line buffers to handle 2D windowing | ||
| + | -- Output | ||
| + | conv_out | ||
| + | ); | ||
| + | end Conv2D; | ||
| + | |||
| + | architecture Behavioral of Conv2D is | ||
| + | |||
| + | -- Line buffers to store previous rows | ||
| + | type line_buffer_type is array (0 to KERNEL_SIZE-2, | ||
| + | signal line_buffer : line_buffer_type; | ||
| + | |||
| + | -- Window buffer to hold current KxK pixels | ||
| + | type window_type is array (0 to KERNEL_SIZE-1, | ||
| + | signal window : window_type; | ||
| + | |||
| + | -- Counters to track position | ||
| + | signal row_cnt, col_cnt : integer range 0 to IMG_SIZE-1 := 0; | ||
| + | |||
| + | begin | ||
| + | |||
| + | process(clk, | ||
| + | begin | ||
| + | if reset = ' | ||
| + | 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, | ||
| + | end loop; | ||
| + | if row_cnt = 0 then | ||
| + | -- First row, no previous data | ||
| + | line_buffer(0, | ||
| + | else | ||
| + | line_buffer(0, | ||
| + | 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, | ||
| + | elsif j = KERNEL_SIZE-1 then | ||
| + | -- from previous line buffer | ||
| + | window(i,j) <= line_buffer(i-1, | ||
| + | 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 => ' | ||
| + | for i in 0 to KERNEL_SIZE-1 loop | ||
| + | for j in 0 to KERNEL_SIZE-1 loop | ||
| + | sum := sum + resize(window(i, | ||
| + | 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 ===== | ||
| + | |||
| + | <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; | ||
| + | reset_n | ||
| + | -- DDR controller interface signals | ||
| + | -- These are placeholder signals; replace with your DDR controller' | ||
| + | ddr_addr | ||
| + | ddr_dq | ||
| + | ddr_dqs | ||
| + | ddr_we_n | ||
| + | ddr_oe_n | ||
| + | ddr_cs_n | ||
| + | -- Control signals for read/write | ||
| + | start_write | ||
| + | start_read | ||
| + | write_data | ||
| + | read_data | ||
| + | write_done | ||
| + | read_done | ||
| + | ); | ||
| + | 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 => ' | ||
| + | signal data_reg : std_logic_vector(63 downto 0) := (others => ' | ||
| + | |||
| + | begin | ||
| + | |||
| + | process(clk, | ||
| + | begin | ||
| + | if reset_n = ' | ||
| + | state <= IDLE; | ||
| + | ddr_we_n <= ' | ||
| + | ddr_oe_n <= ' | ||
| + | ddr_cs_n <= ' | ||
| + | write_done <= ' | ||
| + | read_done <= ' | ||
| + | read_data <= (others => ' | ||
| + | addr_reg <= (others => ' | ||
| + | elsif rising_edge(clk) then | ||
| + | case state is | ||
| + | when IDLE => | ||
| + | write_done <= ' | ||
| + | read_done <= ' | ||
| + | if start_write = ' | ||
| + | addr_reg <= (others => ' | ||
| + | data_reg <= write_data; | ||
| + | state <= WRITE; | ||
| + | elsif start_read = ' | ||
| + | addr_reg <= (others => ' | ||
| + | state <= READ; | ||
| + | end if; | ||
| + | |||
| + | when WRITE => | ||
| + | -- Drive DDR signals for write | ||
| + | ddr_addr <= addr_reg; | ||
| + | ddr_dq <= data_reg; | ||
| + | ddr_we_n <= ' | ||
| + | ddr_oe_n <= ' | ||
| + | ddr_cs_n <= ' | ||
| + | -- Add necessary timing delays as per DDR spec | ||
| + | -- For simplicity, assume one cycle write | ||
| + | write_done <= ' | ||
| + | ddr_we_n <= ' | ||
| + | ddr_cs_n <= ' | ||
| + | state <= IDLE; | ||
| + | |||
| + | when READ => | ||
| + | -- Drive DDR signals for read | ||
| + | ddr_addr <= addr_reg; | ||
| + | ddr_we_n <= ' | ||
| + | ddr_oe_n <= ' | ||
| + | ddr_cs_n <= ' | ||
| + | -- Wait for data to be valid (depends on DDR timing) | ||
| + | -- For simplicity, assume data is ready immediately | ||
| + | read_data <= ddr_dq; | ||
| + | read_done <= ' | ||
| + | ddr_oe_n <= ' | ||
| + | ddr_cs_n <= ' | ||
| + | state <= IDLE; | ||
| + | |||
| + | when others => | ||
| + | state <= IDLE; | ||
| + | end case; | ||
| + | end if; | ||
| + | end process; | ||
| + | |||
| + | end architecture; | ||
| + | </ | ||
| + | |||
| + | ===== 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 | ||
| + | rd_enable | ||
| + | address | ||
| + | write_data | ||
| + | read_data | ||
| + | read_valid | ||
| + | -- SDRAM interface signals (simplified) | ||
| + | sdram_dq | ||
| + | sdram_addr | ||
| + | sdram_ba | ||
| + | sdram_cs_n | ||
| + | sdram_ras_n | ||
| + | sdram_cas_n | ||
| + | sdram_we_n | ||
| + | ); | ||
| + | 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 | ||
| + | |||
| + | -- Internal signals | ||
| + | signal row_address : std_logic_vector(12 downto 0); | ||
| + | signal col_address : std_logic_vector(9 downto 0); | ||
| + | signal data_out | ||
| + | signal data_in | ||
| + | signal data_valid | ||
| + | |||
| + | -- Timing counters (simplified) | ||
| + | signal wait_counter : integer := 0; | ||
| + | |||
| + | begin | ||
| + | |||
| + | process(clk, | ||
| + | begin | ||
| + | if reset = ' | ||
| + | state <= IDLE; | ||
| + | sdram_cs_n <= ' | ||
| + | sdram_ras_n <= ' | ||
| + | sdram_cas_n <= ' | ||
| + | sdram_we_n <= ' | ||
| + | sdram_addr <= (others => ' | ||
| + | sdram_ba <= (others => ' | ||
| + | read_data <= (others => ' | ||
| + | read_valid <= ' | ||
| + | wait_counter <= 0; | ||
| + | elsif rising_edge(clk) then | ||
| + | case state is | ||
| + | when IDLE => | ||
| + | read_valid <= ' | ||
| + | if wr_enable = ' | ||
| + | -- Initiate write sequence | ||
| + | sdram_cs_n <= ' | ||
| + | sdram_ras_n <= ' | ||
| + | sdram_cas_n <= ' | ||
| + | sdram_we_n <= ' | ||
| + | sdram_addr <= address(12 downto 0); -- Column address | ||
| + | sdram_ba <= " | ||
| + | state <= PRECHARGE; | ||
| + | wait_counter <= 2; -- Wait cycles for command | ||
| + | data_out <= write_data; | ||
| + | elsif rd_enable = ' | ||
| + | -- Initiate read sequence | ||
| + | sdram_cs_n <= ' | ||
| + | sdram_ras_n <= ' | ||
| + | sdram_cas_n <= ' | ||
| + | sdram_we_n <= ' | ||
| + | sdram_addr <= address(12 downto 0); | ||
| + | sdram_ba <= " | ||
| + | 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 <= ' | ||
| + | sdram_cas_n <= ' | ||
| + | sdram_we_n <= ' | ||
| + | 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 = ' | ||
| + | -- Issue write command | ||
| + | sdram_ras_n <= ' | ||
| + | sdram_cas_n <= ' | ||
| + | sdram_we_n <= ' | ||
| + | sdram_addr <= address(12 downto 0); -- Column address | ||
| + | state <= WRITE; | ||
| + | wait_counter <= 2; | ||
| + | elsif rd_enable = ' | ||
| + | -- Issue read command | ||
| + | sdram_ras_n <= ' | ||
| + | sdram_cas_n <= ' | ||
| + | sdram_we_n <= ' | ||
| + | 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 <= ' | ||
| + | sdram_ras_n <= ' | ||
| + | sdram_cas_n <= ' | ||
| + | sdram_we_n <= ' | ||
| + | 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 <= ' | ||
| + | sdram_cs_n <= ' | ||
| + | sdram_ras_n <= ' | ||
| + | sdram_cas_n <= ' | ||
| + | sdram_we_n <= ' | ||
| + | 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 ===== | ||
| + | |||
| + | <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, | ||
| + | (to_signed(3, | ||
| + | ); | ||
| + | |||
| + | signal B : matrix_t := ( | ||
| + | (to_signed(5, | ||
| + | (to_signed(7, | ||
| + | ); | ||
| + | |||
| + | -- Result matrix C | ||
| + | signal C : matrix_t := ( | ||
| + | (others => (others => ' | ||
| + | ); | ||
| + | |||
| + | -- Loop counters | ||
| + | signal i, j, k : integer range 0 to N-1 := 0; | ||
| + | |||
| + | -- Accumulator for sum | ||
| + | signal sum : data_t := (others => ' | ||
| + | |||
| + | -- State machine states | ||
| + | type state_type is (IDLE, COMPUTE, DONE); | ||
| + | signal state : state_type := IDLE; | ||
| + | |||
| + | begin | ||
| + | |||
| + | process(clk, | ||
| + | begin | ||
| + | if reset = ' | ||
| + | -- Reset all signals | ||
| + | i <= 0; | ||
| + | j <= 0; | ||
| + | k <= 0; | ||
| + | sum <= (others => ' | ||
| + | C <= (others => (others => ' | ||
| + | state <= IDLE; | ||
| + | done <= ' | ||
| + | |||
| + | elsif rising_edge(clk) then | ||
| + | case state is | ||
| + | when IDLE => | ||
| + | if start = ' | ||
| + | -- Initialize counters | ||
| + | i <= 0; | ||
| + | j <= 0; | ||
| + | k <= 0; | ||
| + | sum <= (others => ' | ||
| + | state <= COMPUTE; | ||
| + | done <= ' | ||
| + | end if; | ||
| + | |||
| + | when COMPUTE => | ||
| + | -- Perform multiplication: | ||
| + | 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 => ' | ||
| + | |||
| + | -- 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 <= ' | ||
| + | -- Optionally, stay here or reset | ||
| + | end case; | ||
| + | end if; | ||
| + | end process; | ||
| + | |||
| + | end architecture; | ||
| + | </ | ||
| + | |||
| + | |||
| + | ==== 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 | ||
| + | pixel_mem_data | ||
| + | pixel_mem_we | ||
| + | -- Output | ||
| + | conv_pixel_out | ||
| + | done : out std_logic | ||
| + | ); | ||
| + | end entity; | ||
| + | |||
| + | architecture Behavioral of convolution_kernel is | ||
| + | |||
| + | -- Define kernel size | ||
| + | constant KERNEL_SIZE : integer := 3; | ||
| + | constant IMG_WIDTH | ||
| + | constant IMG_HEIGHT | ||
| + | |||
| + | -- Convolution kernel (e.g., sharpening kernel) | ||
| + | type kernel_type is array (0 to KERNEL_SIZE-1, | ||
| + | constant kernel : kernel_type := ( | ||
| + | (0, -1, 0), | ||
| + | (-1, 5, -1), | ||
| + | (0, -1, 0) | ||
| + | ); | ||
| + | |||
| + | -- State machine states | ||
| + | type state_type is (IDLE, READ_PIXELS, | ||
| + | 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, | ||
| + | signal pixel_sum : integer := 0; | ||
| + | signal conv_result : unsigned(7 downto 0) := (others => ' | ||
| + | |||
| + | -- 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, | ||
| + | begin | ||
| + | if reset = ' | ||
| + | state <= IDLE; | ||
| + | pixel_mem_addr <= (others => ' | ||
| + | pixel_mem_we <= ' | ||
| + | conv_pixel_out <= (others => ' | ||
| + | done <= ' | ||
| + | x <= 0; | ||
| + | y <= 0; | ||
| + | row <= 0; | ||
| + | col <= 0; | ||
| + | elsif rising_edge(clk) then | ||
| + | case state is | ||
| + | when IDLE => | ||
| + | if start = ' | ||
| + | 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' | ||
| + | pixel_window(i, | ||
| + | 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, | ||
| + | end loop; | ||
| + | end loop; | ||
| + | |||
| + | -- Clamp the result to 0-255 | ||
| + | if pixel_sum < 0 then | ||
| + | conv_result <= (others => ' | ||
| + | elsif pixel_sum > 255 then | ||
| + | conv_result <= (others => ' | ||
| + | else | ||
| + | conv_result <= to_unsigned(pixel_sum, | ||
| + | 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 <= ' | ||
| + | end if; | ||
| + | end if; | ||
| + | state <= IDLE; | ||
| + | |||
| + | when DONE => | ||
| + | -- Processing complete | ||
| + | null; | ||
| + | |||
| + | when others => | ||
| + | null; | ||
| + | end case; | ||
| + | end if; | ||
| + | end process; | ||
| + | |||
| + | end Behavioral; | ||
| + | </ | ||
| + | |||
| + | ==== 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 | ||
| + | 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 => ' | ||
| + | begin | ||
| + | process(clk) | ||
| + | begin | ||
| + | if rising_edge(clk) then | ||
| + | if we = ' | ||
| + | -- 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 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 := ' | ||
| + | signal we       : std_logic := ' | ||
| + | signal addr : std_logic_vector(3 downto 0); | ||
| + | signal data_in | ||
| + | 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 | ||
| + | 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 <= ' | ||
| + | wait for 10 ns; | ||
| + | clk <= ' | ||
| + | wait for 10 ns; | ||
| + | end loop; | ||
| + | end process; | ||
| + | |||
| + | -- Test sequence | ||
| + | stim_proc: process | ||
| + | begin | ||
| + | -- Write data to address 0x1 | ||
| + | addr <= " | ||
| + | data_in <= " | ||
| + | we <= ' | ||
| + | wait for 20 ns; | ||
| + | |||
| + | -- Disable write | ||
| + | we <= ' | ||
| + | wait for 20 ns; | ||
| + | |||
| + | -- Read from address 0x1 | ||
| + | addr <= " | ||
| + | wait for 20 ns; | ||
| + | |||
| + | -- Write data to address 0x2 | ||
| + | addr <= " | ||
| + | data_in <= " | ||
| + | we <= ' | ||
| + | wait for 20 ns; | ||
| + | |||
| + | -- Disable write | ||
| + | we <= ' | ||
| + | wait for 20 ns; | ||
| + | |||
| + | -- Read from address 0x2 | ||
| + | addr <= " | ||
| + | wait for 20 ns; | ||
| + | |||
| + | wait; | ||
| + | end process; | ||
| + | end architecture; | ||
| + | </ | ||
| + | |||
| + | < | ||
| + | Compile: | ||
| + | Elaborate: | ||
| + | Run the simulation: ghdl -r tb_ram --wave=wave.ghw | ||
| + | View waveform: | ||
| + | </ | ||
| + | |||
| + | |||
| + | ==== 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 " | ||
| + | |||
| + | signal data : std_logic_vector(7 downto 0) := (others => ' | ||
| + | begin | ||
| + | process | ||
| + | begin | ||
| + | wait for 10 ns; | ||
| + | external_procedure(data); | ||
| + | wait; | ||
| + | end process; | ||
| + | end architecture; | ||
| + | </ | ||
| + | |||
| + | <code c> | ||
| + | #include < | ||
| + | #include " | ||
| + | |||
| + | // 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(" | ||
| + | |||
| + | // Modify the signal (e.g., increment) | ||
| + | *signal_value = (*signal_value + 1) & 0xFF; | ||
| + | |||
| + | printf(" | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | < | ||
| + | gcc -shared -fPIC -o ghdl_fli_example.so ghdl_fli_example.c | ||
| + | ghdl -a testbench.vhd | ||
| + | ghdl -Wl, | ||
| + | ghdl -r testbench --stop-time=50ns | ||
| + | </ | ||
| + | |||
| + | https:// | ||
| + | |||
vhdl.1761767079.txt.gz · Last modified: 2025/10/29 19:44 by 147.32.8.31
                
                