📄 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
oen: out STD_LOGIC;
wen: out STD_LOGIC;
readAddr: out STD_LOGIC_VECTOR(19 downto 0);
readData: in STD_LOGIC_VECTOR(15 downto 0);
startAddr : in STD_LOGIC_VECTOR(19 downto 0);
tableSize : in std_logic_vector(2 downto 0)
);
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, stSetup2RGB, stSetup3RGB, stWriteRGB, stNextWriteRGB
);
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)
"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
-- 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;
signal currAddr: STD_LOGIC_VECTOR (19 downto 0);
signal incCurrAddr: STD_LOGIC;
signal byteData : STD_LOGIC_VECTOR(7 downto 0);
signal tableSizeInt : integer;
signal two, maxColor10 : std_logic_vector(9 downto 0);
signal maxColor : std_logic_vector(7 downto 0);
begin
-- always read from memory, never write
oen <= '0';
wen <= '1';
readAddr <= currAddr;
-- compute the ending address of the color table
tableSizeInt <= conv_integer(tableSize);
two <= "0000000010";
maxColor10 <= SHL(two, tableSize) - 1;
maxColor <= maxColor10(7 downto 0);
-- clock divider by 4 to for a slower clock to avoid timing violations
-- uses grey code for minimized logic
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 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;
elsif divclk'event and divclk = '1' then
if start = '1' then
currAddr <= startAddr;
initCnt <= 0;
colourCnt <= (others => '0');
prgRGB <= (others => '0');
end if;
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;
if incColourCnt = '1' then
if colourCnt = "10" then
colourCnt <= "00";
prgRGB <= prgRGB + 1;
else
colourCnt <= colourCnt + 1;
end if;
end if;
if incCurrAddr = '1' then
currAddr <= currAddr + 1;
end if;
end if;
end process;
byteData <= readData(7 downto 0);
--byteData <= prgRGB when colourCnt = "00" else
-- x"00";
prgData <= initDAC(initCnt) when presState = stIdle or presState = stWrite or
presState = stWrCycle or presState = stNextWrite
else byteData;
-- 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';
prgRS <= "001";
latchData <= '1';
latchRS <= '1';
done <= '0';
incCurrAddr <= '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);
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);
WRn <= '0';
when stWrCycle =>
-- continue if all 5 registers that needed programming have been written to
if initCnt = 5 then
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);
-- increment initCnt to program the next register
increment <= '1';
when stNextWrite =>
nextState <= stWrite;
-- setup for the next write cycle
prgRS <= initRS(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 <= stSetup2RGB;
when stSetup2RGB =>
nextState <= stSetup3RGB;
when stSetup3RGB =>
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 = maxColor and colourCnt = "10" then
nextState <= stIdle;
done <= '1';
else
nextState <= stSetupRGB;
end if;
incColourCnt <= '1';
incCurrAddr <= '1';
end case;
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 + -