在线咨询
eetop公众号 创芯大讲堂 创芯人才网
切换到宽版

EETOP 创芯网论坛 (原名:电子顶级开发网)

手机号码,快捷登录

手机号码,快捷登录

找回密码

  登录   注册  

快捷导航
搜帖子
查看: 2799|回复: 1

如何实现Set Address命令和左右漂移

[复制链接]
发表于 2007-11-26 09:39:36 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?注册

x
在下面这个程序里,只有2个命令 Clear(CL)和Load(LD),如何才能实现Set Address命令 使得可以下载数据到任意一个想要的地址呀? 还有怎么才能实现Left Shift(LT)和Right Shift(RT)呢??
初学VHDL实在是不会


-------------------------------------------------------------------------------
-- MessageReceiver.vhd
-------------------------------------------------------------------------------
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_unsigned.all;
entity MessageReceiver is
     port (
  Clock:    in  std_logic;  -- Synchronous system clock, 50MHz
  Reset:    in  std_logic;  -- Synchronous system reset, active high

  RXD:     in  std_logic;  -- RS232 serial receive signal
  usr_data:   out std_logic_vector(7 downto 0); -- 8-bit data to send to the LCD driver
  usr_data_ncmd: out std_logic;  -- = '1' if usr_data carries a character, '0' if command
  usr_write:  out std_logic;  -- LCD write enable signal, active high, one clock cycle in width
  usr_busy:  in  std_logic  -- Busy signal from the LCD driver, active high
);
end MessageReceiver;
architecture MessageReceiver_arch of MessageReceiver is
-- component declarations
component dpram128x8
    port (
    addra: IN std_logic_VECTOR(6 downto 0);
    addrb: IN std_logic_VECTOR(6 downto 0);
    clka: IN std_logic;
    clkb: IN std_logic;
    dina: IN std_logic_VECTOR(7 downto 0);
    doutb: OUT std_logic_VECTOR(7 downto 0);
    enb: IN std_logic;
    wea: IN std_logic);
end component;
component Rs232Rxd
port(
Reset, Clk, Rxd:  in std_logic;
DataEn:  out std_logic;
Data:   out std_logic_vector (7 downto 0));
end component;
-- Internal signals
-- DPRAM interface signals
signal iBufWriteAddress, iBufReadAddress: std_logic_vector (6 downto 0);
signal iBufReadData: std_logic_vector (7 downto 0);
signal iBufReadEnable: std_logic;
-- 8-bit array signal of size 3 to detect a valid message header
type LcdActionType is array(2 downto 0) of std_logic_vector(7 downto 0);
signal iLcdOperation: LcdActionType;
signal iRs232DataEnable, iCmdEnd: std_logic;
signal iRs232Data: std_logic_vector (7 downto 0);
-- State definition for the state machine of the message pre-processing
type stateTypeMSG is (stIdleMSG, stReadBufMSG, stLoadDataMSG);
signal presStateMSG: stateTypeMSG;
signal nextStateMSG: stateTypeMSG;
signal iBufReadEnableMSG: std_logic;
signal iClearMSG, iLoadDataMSG: std_logic;
signal iBufReadAddressMSG: std_logic_vector (6 downto 0);
-- State definition for the 'Clear' state machine
type stateTypeCL is (stIdleCL, stClearWaitCL, stCursorCL, stCursorWaitCL);
signal presStateCL: stateTypeCL;
signal nextStateCL: stateTypeCL;
signal iLcdDataCL: std_logic_vector (7 downto 0);
signal iLcdDataValidCL, iLcdWriteCL: std_logic;
-- State definition for the 'Load' state machine
type stateTypeLD is (stIdleLD, stLocateSpaceLD, stSendCmdLD, stWaitLD);
signal presStateLD: stateTypeLD;
signal nextStateLD: stateTypeLD;
signal iLcdDataLD: std_logic_vector (7 downto 0);
signal iLcdDataValidLD, iLcdWriteLD, iBufReadEnableLD, iRstBufReadAddressLD, iIncBufReadAddressLD: std_logic;
signal iBufReadAddressLD: std_logic_vector (6 downto 0);
begin
-- RS232 Receiver
Rs232Receiver: RS232Rxd
   port map (
    Reset => Reset,
    Clk => Clock,
    Rxd => RXD,
    DataEn => iRs232DataEnable,
    Data => iRs232Data);
-- Generate write address to write received RS232RxD data to the dual-port RAM
   -- The address is increased by one every cycle while the RS232 data enable signal is valid
   -- and reset when an <Enter> character is received.
PROC_WRITE_ADDRESS: process (Clock)
begin
  if rising_edge(Clock) then
   if (Reset = '1' or iCmdEnd = '1') then
    iBufWriteAddress <= (others=>'0');  
   elsif iRs232DataEnable = '1' then
    iBufWriteAddress <= iBufWriteAddress + 1;  
   end if;
  end if;
end process;

   -- Instance of the Dual-Port RAM(DPRAM) component created from Xilinx core generator
   --  Port A: Write the data received from RS232RxD
   --  Port B: Read out the data for message processing
   --
   -- Data written to the DPRAM is in ASCII coding
   -- Two Message commands have been defined and implemented in the basic message display design:
   --  'CL<Enter>'     - to clear the LCD screen
   --  'LD xyz<Enter>' - to display string 'xyz' from the current position
   --                      of the cursor on the LCD screen.
   -- Messages are always terminated by a <Enter> (or X"0D") character.
   -- Only one message can be stored in the DPRAM.
--
RxdBuffer: dpram128x8
        port map (
            addra => iBufWriteAddress,
            addrb => iBufReadAddress,
            clka => Clock,
            clkb => Clock,
            dina => iRs232Data,
            doutb => iBufReadData,
            enb => iBufReadEnable,
            wea => iRs232DataEnable);
   
-- A multiplexer for the read address of the DPRAM.
-- In the basic message display design, the read address is routed to
-- the read address generated in the 'MSG' state machine
-- when the 'message' state machine takes control of reading the DPRAM, otherwise,  
-- it is routed to the read address generated in in the 'LOAD' state machine
iBufReadAddress <= iBufReadAddressMSG when (iBufReadEnableMSG = '1') else
        iBufReadAddressLD;
-- The DPRAM read enable signls will be valid whenver any state machine needs to read the DPRAM.
-- In the basic message display design, only two state machines of 'MSG' and 'LOAD' needs to access the DPRAM
iBufReadEnable <= iBufReadEnableMSG or iBufReadEnableLD;
   
   -- A process to detect the end of a message or when received an <Enter> character
PROC_CMD_END: process (Clock)
begin
  if rising_edge(Clock) then
   if iRs232Data = x"0D" and iRs232DataEnable = '1' then
    iCmdEnd <= '1';  
   else
    iCmdEnd <= '0';  
   end if;
  end if;
end process;
  
-- MSG state machine to pre-process the message read out from the DPRAM,
SM_MSG_SYNC: process (Clock)
begin
  if rising_edge(Clock) then
   
   -- State transaction
   if Reset = '1' then
    presStateMSG <= stIdleMSG;
   else
    presStateMSG <= nextStateMSG;
   end if;
   
   -- The DPRAM read address generation
   if (Reset= '1' or iCmdEnd = '1') then
    iBufReadAddressMSG <= (others => '0');   
   elsif iBufReadEnableMSG = '1' then
    iBufReadAddressMSG <= iBufReadAddressMSG + 1;
   end if;
   -- A shifter to remember 3 last characters (used to detect a valid message header)
   if iBufReadEnableMSG = '1' then
    iLcdOperation <= iLcdOperation(1 downto 0) & iBufReadData;
   end if;
  end if;
end process;

SM_MSG_ASYNC: process (presStateMSG, iCmdEnd, iLcdOperation, iBufReadData)
begin
  -- Signal defaults
  iBufReadEnableMSG <= '0';
  iClearMSG   <= '0';
  iLoadDataMSG  <= '0';
  -- State actions
  case presStateMSG is
   
         -- IDLE -> wait until a whole message is written to the DPRAM (ended with <Enter>)
   when stIdleMSG =>
    if iCmdEnd = '1' then
     nextStateMSG <= stReadBufMSG;
    else
     nextStateMSG <= stIdleMSG;
    end if;
     
         -- Read the DPRAM until three continual characters match the pre-defined message header
   when stReadBufMSG =>
    iBufReadEnableMSG <= '1';
   
            -- Test if they match 'CL<Enter>'
    if iLcdOperation = (x"43", x"4C", x"0D") then
     iClearMSG <= '1';   -- Issue 'Clear' pulse
     nextStateMSG <= stIdleMSG;
   
            -- Test if they match 'LD '   
    elsif iLcdOperation = (x"4C", x"44", x"20") then
     nextStateMSG <= stLoadDataMSG;
    else
     nextStateMSG <= stReadBufMSG;
    end if;
   
         -- Keep reading the DPRAM until it reaches <enter>
   when stLoadDataMSG =>
    iBufReadEnableMSG <= '1';
    if iBufReadData = x"0D" then
     iLoadDataMSG <= '1';  -- Issue 'Load' pulse
     nextStateMSG <= stIdleMSG;
    else
     nextStateMSG <= stLoadDataMSG;
    end if;
  end case;
end process;

-- CLEAR State machine for Clear operation
SM_CLEAR_SYNC: process (Clock)
begin
  if rising_edge(Clock) then
   
   -- State transaction
   if Reset = '1' then
    presStateCL <= stIdleCL;
   else
    presStateCL <= nextStateCL;
   end if;
   
  end if;
end process;

SM_CLEAR_ASYNC: process (presStateCL, iClearMSG, usr_busy)
begin
  -- Signal defaults
  iLcdDataValidCL <= '0';
  iLcdDataCL   <= x"00";
  iLcdWriteCL   <= '0';
  
  -- State actions
  case presStateCL is
  
   -- Wait for a 'Clear' pulse from MSG state machine
   when stIdleCL =>
    if iClearMSG = '1' then
     iLcdDataValidCL <= '1'; -- Take control of the LCD data bus
     iLcdDataCL <= x"01";  -- Output "Clear Display" command to the LCD data bus
     iLcdWriteCL <= '1';  -- Set LCD Write signal
     nextStateCL <= stClearWaitCL;
    else
     nextStateCL <= stIdleCL;
    end if;
         -- Wait while the LCD driver is busy
   when stClearWaitCL =>
    if usr_busy = '0' then
     nextStateCL <= stCursorCL;
    else
     nextStateCL <= stClearWaitCL;
    end if;
         -- Set "Display On/Off" to:
   --  (1) "Display character stored in DD RAM"
     --  (2) "Display cursor"
   --  (3) "Cursor blinks on and off approximately every half second"
   when stCursorCL =>
    iLcdDataValidCL <= '1'; -- Take control of the LCD data bus   
    iLcdDataCL <= x"0F";  -- Output "Display On/Off" command to the LCD data bus
    iLcdWriteCL <= '1';  -- Set LCD Write signal
    nextStateCL <= stCursorWaitCL;
         -- Wait while the LCD driver is busy
   when stCursorWaitCL =>
    if usr_busy = '0' then
     nextStateCL <= stIdleCL;
    else
     nextStateCL <= stCursorWaitCL;
    end if;
  end case;
end process;
-- LOAD state machine for Load Data operation
   -- to read data from the DPRAM and then
   -- send them to the LCD driver.
SM_LOAD_SYNC: process (Clock)
begin
  if rising_edge(Clock) then
   
   -- State transaction
   if Reset = '1' then
    presStateLD <= stIdleLD;
   else
    presStateLD <= nextStateLD;
   end if;
   
   -- Read address counter
   if iRstBufReadAddressLD = '1' then
    iBufReadAddressLD <= (others=>'0');
   elsif iIncBufReadAddressLD = '1' then
    iBufReadAddressLD <= iBufReadAddressLD + 1;
   end if;
  end if;
end process;

SM_LOAD_DATA_ASYNC: process (presStateLD, iLoadDataMSG, iBufReadData, usr_busy)
begin
  -- Signal defaults
  iLcdDataValidLD  <= '0';
  iRstBufReadAddressLD <= '0';
  iIncBufReadAddressLD <= '0';
  iLcdDataLD    <= x"00";
  iLcdWriteLD    <= '0';
  iBufReadEnableLD  <= '0';
  -- State actions
  case presStateLD is
   
   -- Wait for a 'Load' pulse from MSG state machine
   when stIdleLD =>
    if iLoadDataMSG = '1' then
     iLcdDataValidLD <= '1';
     iBufReadEnableLD <= '1';   -- Read the first character (should be 'L')
     iIncBufReadAddressLD <= '1';  -- Reset read address to the DPRAM
     nextStateLD <= stLocateSpaceLD;
    else
     iRstBufReadAddressLD <= '1';
     nextStateLD <= stIdleLD;
    end if;
         -- Skip the message header ('LD ')
   when stLocateSpaceLD =>
    iLcdDataValidLD <= '1';
    iBufReadEnableLD <= '1';  -- Read out next character from the DPRAM
    iIncBufReadAddressLD <= '1'; -- Increase address to next memory location
    if iBufReadData = x"20" then
     nextStateLD <= stSendCmdLD;
    else
     nextStateLD <= stLocateSpaceLD;
    end if;
   
         -- Send read data to the LCD driver
   when stSendCmdLD =>
    iLcdDataValidLD <= '1';
    iBufReadEnableLD <= '1';
    iLcdDataLD <= iBufReadData;
    iLcdWriteLD <= '1';
    nextStateLD <= stWaitLD;
         -- Wait while the LCD driver is busy and
   -- then read out next character from the DPRAM until reaching an <Enter>
   when stWaitLD =>
    iLcdDataValidLD <= '1';
    iBufReadEnableLD <= '1';
    if usr_busy = '0' then
     iIncBufReadAddressLD <= '1';
     nextStateLD <= stSendCmdLD;
     if iBufReadData = x"0D" then     
      nextStateLD <= stIdleLD;
     end if;
    else
     nextStateLD <= stWaitLD;
    end if;
  end case;
end process;

   -- Only LOAD state machine needs to set usr_data_ncmd to HIGH to indicate that
-- it is a data session NOT a command session, in other words, so it is simply driven by LOAD state machine only.  
usr_data_ncmd <= iLcdDataValidLD;
   -- Any state machine that needs to control the LCD driver can produce
-- its own LCD write signal to access the LCD driver.
-- In the basic message display design, the LCD write signals generated from
-- both 'CLEAR' state machine and 'LOAD' state machine are or-ed and routed to usr_write
usr_write <= iLcdWriteCL or iLcdWriteLD;
-- A multiplexer for usr_data of the LCD driver.
-- In the basic message display design, usr_data is routed to
-- the LCD data generated in the 'CLEAR' state machine
-- when the 'CLEAR' state machine takes control of the LCD driver, otherwise,  
-- it is routed to the LCD data generated in in the 'LOAD' state machine
usr_data <= iLcdDataCL when (iLcdDataValidCL = '1') else
     iLcdDataLD;

end MessageReceiver_arch;
 楼主| 发表于 2007-11-29 04:10:17 | 显示全部楼层
:(
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

站长推荐 上一条 /1 下一条


小黑屋| 手机版| 关于我们| 联系我们| 在线咨询| 隐私声明| EETOP 创芯网
( 京ICP备:10050787号 京公网安备:11010502037710 )

GMT+8, 2024-11-15 08:34 , Processed in 0.030696 second(s), 11 queries , Gzip On, Redis On.

eetop公众号 创芯大讲堂 创芯人才网
快速回复 返回顶部 返回列表