📄 prgramdac.vhd
字号:
-------------------------------------------------------------------------------
-- prgramdac.vhd
--
-- Author(s): Ashley Partis and Jorgen Peddersen
-- Created: Dec 2000
-- Last Modified: Jan 2001
--
-- This code programmes the RAMDAC on the XSV-300 board with data for either
-- high-colour mode or a simple colour map.
--
-------------------------------------------------------------------------------
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_unsigned.all;
entity prgramdacver2 is
port (
clk: in STD_LOGIC; -- Clock
rstn: in STD_LOGIC; -- Asynchronous active low reset
start: in STD_LOGIC; -- Start signal
done: out STD_LOGIC; -- Asserted when programming is finished
WRn: out STD_LOGIC; -- Write line to RAMDAC (active low)
RDn: out STD_LOGIC; -- Read line to RAMDAC (active low)
RS: inout STD_LOGIC_VECTOR (2 downto 0); -- Register select lines to the RAMDAC
data: inout STD_LOGIC_VECTOR (7 downto 0) -- Bidirectional data line to RAMDAC
);
end prgramdacver2;
architecture prgramdacver2_arch of prgramdacver2 is
-- signal declarations
-- FSM states for the main mealy FSM
type STATETYPE is (stIdle, stWrite, stWrCycle, stNextWrite
--, stSetupRGB, stWriteRGB, stNextWriteRGB -- uncomment these states for colour map
);
signal presState: STATETYPE;
signal nextState: STATETYPE;
-- hardcoded values for initialising the RAMDAC to the values we desire
-- location 10 down to 8 is the RS values
type TWODIMARRAYDAC is array (0 to 5) of STD_LOGIC_VECTOR (7 downto 0);
type TWODIMARRAYRS is array (0 to 5) of STD_LOGIC_VECTOR (2 downto 0);
constant initDAC: TWODIMARRAYDAC:=
-- hard code initial control register programming values
( -- DAC(76543210)
"10000001", -- Command reg A gets $81 for high colour dual edged mode
-- "10100001", -- Command reg A gets $A1 for high colour single edged mode
-- "00000001", -- Command reg A gets $01 for colour map
"00000000", -- Pallette address reg gets $00
"11111111", -- Read mask reg gets $FF
"00000010", -- Pallette address reg gets $02
"00000010", -- Command reg B gets $02
"00000000" -- Pallette address reg gets $00
);
constant initRS: TWODIMARRAYRS:=
( -- RS(210)
"110", -- RS gets Command reg A
"000", -- RS gets Pallette address reg
"010", -- RS gets Read mask reg
"000", -- RS gets Pallette address reg
"010", -- RS gets Command reg B
"000" -- RS gets Pallette address reg
);
-- initCnt is an integer to index the constant two dimensional arrays initDAC and initRS,
-- and a signal to increment initCnt
signal initCnt: INTEGER range 0 to 5;
signal increment: STD_LOGIC;
-- signals to create a 12.5MHz clock from the 50MHz input clock to the entity
signal divclk: STD_LOGIC;
signal gray_cnt: STD_LOGIC_VECTOR (1 downto 0);
-- create signals so the data and RS lines can be used as tristate buffers
-- this is important as they share lines with the ethernet PHY
signal prgData: STD_LOGIC_VECTOR (7 downto 0);
signal prgRS: STD_LOGIC_VECTOR (2 downto 0);
signal latchData: STD_LOGIC;
signal latchRS: STD_LOGIC;
-- these are for programming the colourmap of the RAMDAC - to program all 256 lots
-- of 3 byte sets of RGB data - uncomment for colour map
-- also a signal to increment colourCnt to avoid a race condition
--signal prgRGB: STD_LOGIC_VECTOR (7 downto 0);
--signal colourCnt: STD_LOGIC_VECTOR (1 downto 0);
--signal incColourCnt: STD_LOGIC;
begin
-- clock divider by 4 to for a slower clock to avoid timing violations
-- uses grey code for minimized logic
A: process (rstn, clk)
begin
if rstn = '0' then
gray_cnt <= "00";
elsif clk'EVENT and clk = '1' then
case(gray_cnt) is
when "00" => gray_cnt <= "01";
when "01" => gray_cnt <= "11";
when "11" => gray_cnt <= "10";
when "10" => gray_cnt <= "00";
when others => gray_cnt <= "00";
end case;
end if;
end process;
-- assign the clock that this entity runs off
divclk <= gray_cnt(1);
-- read isn't needed, tie high
RDn <= '1';
-- main clocked process
B: process (rstn, divclk)
begin
if rstn = '0' then
presState <= stIdle;
initCnt <= 0;
-- add these signals for colour map
-- colourCnt <= (others => '0');
-- prgRGB <= (others => '0');
elsif divclk'event and divclk = '1' then
presState <= nextState;
-- increment initCnt
if increment = '1' then
-- overflow initCnt when it hits 5 as integers don't overflow
if initCnt < 5 then
initCnt <= initCnt + 1;
else
initCnt <= 0;
end if;
end if;
-- add these signals for colour map
-- if incColourCnt = '1' then
-- if colourCnt = "10" then
-- colourCnt <= "00";
-- prgRGB <= prgRGB + 1;
-- else
-- colourCnt <= colourCnt + 1;
-- end if;
-- end if;
end if;
end process;
-- Main FSM process
C: process (presState, start, initCnt)
begin
-- default signals and outputs for each FSM state
-- note that the latch data and rs signals are defaulted to 1, so are
-- only 0 in the idle state
WRn <= '1';
increment <= '0';
-- incColourCnt <= '0';
prgData <= (others => '0');
prgRS <= "001";
latchData <= '1';
latchRS <= '1';
done <= '0';
case presState is
when stIdle =>
-- wait for start signal from another process
if start = '1' then
nextState <= stWrite;
-- setup for the first write to the RAMDAC for use by setting the register select
-- lines and the data lines
prgRS <= initRS(initCnt);
prgData <= initDAC(initCnt);
else
nextState <= stIdle;
latchData <= '0';
latchRS <='0';
end if;
when stWrite =>
-- hold the register select and data lines for the write cycle
-- and set the active low write signal
nextState <= stWrCycle;
prgRS <= initRS(initCnt);
prgData <= initDAC(initCnt);
WRn <= '0';
when stWrCycle =>
-- continue if all 5 registers that needed programming have been written to
if initCnt = 5 then
nextState <= stIdle;
done <= '1';
-- comment the two lines above and uncomment the one below for a colour map
-- nextState <= stSetupRGB;
-- continue writing to the registers
else
nextState <= stNextWrite;
end if;
-- hold the data to be sure the hold times aren't violated
prgRS <= initRS(initCnt);
prgData <= initDAC(initCnt);
-- increment initCnt to program the next register
increment <= '1';
when stNextWrite =>
nextState <= stWrite;
-- setup for the next write cycle
prgRS <= initRS(initCnt);
prgData <= initDAC(initCnt);
-- start programming the RGB values to the colour map
-- note RS is defaulted to 001, which is what is required
-- for programming the colour map
-- These steps program the RAMDACs colour map. To set the colours
-- see the if statement below the end of the case statement
-- when stSetupRGB =>
-- nextState <= stWriteRGB;
-- when stWriteRGB =>
-- nextState <= stNextWriteRGB;
-- WRn <= '0';
-- when stNextWriteRGB =>
-- -- if all 256 sets of 3 byte RGB values are programmed, then go back
-- -- to the idle state and assert done
-- if prgRGB = "11111111" and colourCnt = "10" then
-- nextState <= stIdle;
-- done <= '1';
-- else
-- nextState <= stSetupRGB;
-- end if;
-- incColourCnt <= '1';
end case;
-- the following statement will program the RAMDACs colour map. To change the
-- colours it programs with, comment out different lines
-- if presState = stSetupRGB or presState = stWriteRGB or presState = stNextWriteRGB then
-- if colourCnt = "00" then -- Red component
-- prgData <= prgRGB; -- Full Red scaling
-- prgData <= prgRGB(7 downto 5) & "11111";-- 3:3:2 Red scaling
-- prgData <= (others => '0'); -- No Red component
-- elsif colourCnt = "01" then -- Green component
-- prgData <= prgRGB; -- Full Green scaling
-- prgData <= prgRGB(4 downto 2) & "11111";-- 3:3:2 Green scaling
-- prgData <= (others => '0'); -- No Green component
-- else -- Blue component
-- prgData <= prgRGB; -- Full Blue scaling
-- prgData <= prgRGB(1 downto 0) & "11111";-- 3:3:2 Blue scaling
-- prgData <= (others => '0'); -- No Blue component
-- end if;
-- Leave the following line commented if using the if statement above
-- prgData <= prgRGB; -- Full Grey scaling
-- end if;
end process;
--
-- assign data and RS prgData and prgRS repsectively when they need to be latched
-- otherwise keep them at high impedance to create a tri state buffer
data <= prgData when latchData = '1' else (others => 'Z');
RS <= prgRS when latchRS = '1' else (others => 'Z');
end prgramdacver2_arch;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -