Code:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity FrameBuffer is
port
(
data_a : in std_logic_vector(15 downto 0);
data_b : in std_logic_vector(15 downto 0);
addr_a : in natural range 0 to 80999;
addr_b : in natural range 0 to 80999;
we_a : in std_logic ;
we_b : in std_logic ;
clk_106 : in std_logic;
q_a : out std_logic_vector(15 downto 0);
q_b : out std_logic_vector(15 downto 0)
);
end FrameBuffer;
architecture rtl of FrameBuffer is
-- Build a 2-D array type for the RAM
subtype word_t is std_logic_vector(15 downto 0);
type memory_t is array(0 to 80999) of word_t;
FUNCTION initialize_ram
return memory_t is
variable result : memory_t;
BEGIN
FOR i IN 0 to 80999 LOOP
result(i) := "1111111111111111";
END LOOP;
RETURN result;
END initialize_ram;
-- Declare the RAM
shared variable ram : memory_t :=initialize_ram ;
begin
-- Port A
process(clk_106)
begin
if(rising_edge(clk_106)) then -- Port A
if(we_a = '1') then
ram(addr_a) := data_a;
-- Read-during-write on the same port returns NEW data
q_a <= data_a;
else
-- Read-during-write on the mixed port returns OLD data
q_a <= ram(addr_a);
end if;
end if;
end process;
-- Port B
process(clk_106)
begin
if(rising_edge(clk_106)) then -- Port B
if(we_b = '1') then
ram(addr_b) := data_b;
-- Read-during-write on the same port returns NEW data
q_b <= data_b;
else
-- Read-during-write on the mixed port returns OLD data
q_b <= ram(addr_b);
end if;
end if;
end process;
end rtl;
This is my inferred RAM. I confirmed it from the design summary, it does indeed use memory bits inside the FPGA. The reason I used
write in both cases is because I coded the RAM by using write enable signals. However I do not think it is the root to any problem.
I think I managed to write data inside the RAM, but now I am stuck with feeding my data to DVI. For the time being I hold 1 bit per pixel inside the ram, and conclude the 24bit color inside the DVI block I designed. The color depends on the coordinate of the hcounter and vcounter. So, reading 16 bits from the RAM is not enough to pass it on to DVI, I need to pass it bit by bit at each clock edge.
Currently I do it as follows:
Code:
process(clk106M, locked_sgnl)
begin
if locked_sgnl = '0' then
address_counter <= (others => '0');
counter <= "10000";
pixel_in_register <= (others => '0');
elsif rising_edge(clk106M) and (locked_sgnl = '1') then
if (address_counter < "10011110001101000") then
if counter >= 16 then
pixel_in_register <= pixel_in;
address_counter <= address_counter + '1';
counter <= "00000";
else
pixel_in_sgnl <= pixel_in_register(0);
pixel_in_register <= '0' & pixel_in_register(15 downto 1);
counter <= counter + '1';
end if;
else
address_counter <= (others => '0');
end if;
end if;
end process;
buffer_address_dvi <= address_counter;
I use a register and hold the buffer output inside. Then at each clock cycle for 16 cycles, I output the LSB of the contents of the register and shift the data to right. What stucks in my head is that if I need to generate the read address earlier or not.
Currently if there is a 0 in buffer, that pixel corresponds to green. If 1, it corresponds to blue. What I do is that I instantiate the RAM full of '1's. Then I write '0' to a portion of it, and try to observe a thick horizontal line on the screen. Fortunately enough, I see that horizontal line, but it is not stationary. Its sweeping the screen from top to bottom or bottom to top, I can not differentiate. What might the cause of that particular issue?