おいふぉりーのぶろぐ

きっと趣味のブログに違いないです!!

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。
  1. --/--/--(--) --:--:--|
  2. スポンサー広告

[MAXII]再び

さて、InRoFが終わって早々、VHDLを弄りたくなってコーディングしていました。とりあえず、SPXのインターフェースをハードウェアで実装しようとしてます。まず、シリアル通信モジュールが必要なんですが、前に実装したやつは1バイトの送受信バッファとかをしっかり入れて実装していたのでトラ技MAXIIでは50%もLEを食ってしまいます。そこで、半二重通信用のシリアルモジュールをコーディングしてみました。できるだけ軽量化したいので、送受信バッファも除きました。あと、ボーレートの変更が楽にできるように、ボーレート計測用レジスタの幅とリロード値をパラメタライズしました。で、LEの使用量ですがなんとかノーマルのフィットオプションで40LE、トラ技MAXIIで17%に抑えました。正直もっとコンパクトにしたかったんですが、結果を見てみると組み合わせの配線領域(LUT)が結構食っていることが分かりました。組み合わせ領域のみを使用しているLEが19、レジスタのみ使用しているLEは0、組み合わせ領域とレジスタを両方使用しているLEが21でした。えーと、ソースは続きを読んでくださいな。
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;

entity HalfUart is
  generic (
    BR_Width  : integer := 7;
    BR_Max    : integer := 124
  );
  port (
    --dbgBR       : out std_logic_vector(6 downto 0);
    --dbgStat     : out std_logic_vector(3 downto 0);
    --dbgStartTr  : out std_logic;
    --dbgStartRc  : out std_logic;
    --dbgBRZ      : out std_logic;

    iClock  : in std_logic;                     -- Clock
    iNReset : in std_logic;                     -- Reset

    iData   : in std_logic_vector(7 downto 0);  -- intput Data
    oData   : out std_logic_vector(7 downto 0); -- output Data (is enabled when oNotify = '1')
    iWrite  : in std_logic;                     -- Write to shift register
    oNotify : out std_logic;                    -- notify receive completion
    oBusy   : out std_logic;                    -- output busy signal

    iRXD    : in std_logic;                     -- RXD
    oTXD    : out std_logic                     -- TXD
  );
end HalfUart;

architecture rtl of HalfUart is
  signal regRXD     : std_logic;                    -- RXD synchronous register
  signal sregBuf    : std_logic_vector(7 downto 0); -- shift register for reception, transmission
  signal cntBR      : std_logic_vector(BR_Width - 1 downto 0);  -- counter for baudrate measurement
  signal cntStat    : std_logic_vector(3 downto 0); -- counter showing reception state
  signal fTr        : std_logic;                    -- whether transmitting

  signal fIdle      : std_logic;                    -- whether idleing
  signal fStart     : std_logic;                    -- whether start bit
  signal fData      : std_logic;                    -- whether data
  signal fStop      : std_logic;                    -- whether stop bit

  signal trgBRZ     : std_logic;                    -- whether cntRcBR is zero
  signal trgBRM     : std_logic;                    -- whether cntRcBR is middle
  signal trgStartRc : std_logic;                    -- start receiving
  signal trgStartTr : std_logic;                    -- start transmitting
  signal trgShift   : std_logic;                    -- shift trigger

begin
  -- debug
  --dbgBR <= cntBR;
  --dbgStat <= cntStat;
  --dbgStartTr <= trgStartTr;
  --dbgStartRc <= trgStartRc;
  --dbgBRZ <= trgBRZ;

  -- state
  fIdle <= '1' when (cntStat = "0000") else '0';
  fStart <= '1' when (cntStat = "1010") else '0';
  fData <= (not fIdle) and (not fStart) and (not fStop);
  fStop <= '1' when (cntStat = "0001") else '0';

  -- trigger
  trgBRZ <= '1' when (cntBR = conv_std_logic_vector(0, BR_Width)) else '0';
  trgBRM <= '1' when (cntBR = conv_std_logic_vector(BR_Max / 2, BR_Width)) else '0';
  trgStartRc <= '1' when ((fIdle = '1' or fStop = '1') and regRXD = '0') else '0';
  trgStartTr <= '1' when (fIdle = '1' and iWrite = '1') else '0';
  trgShift <= trgBRZ when (fTr = '1') else trgBRM;

  -- output signal
  oData <= sregBuf;
  oNotify <= fStop and trgBRM and regRXD and (not fTr);
  oBusy <= not fIdle;
  oTXD <= '0' when (fTr = '1' and fStart = '1') else
          sregBuf(0) when (fTr = '1' and fData = '1') else
          '1';

  process (iClock, iNReset)
  begin
    if (iNReset = '0') then
      regRXD <= '1';
      sregBuf <= (others => '0');
      cntBR <= (others => '0');
      cntStat <= (others => '0');
      fTr <= '0';
    elsif (iClock'event and iClock = '1') then
      -- synchronize RXD input
      regRXD <= iRXD;

      -- process state
      if (trgStartRc = '1' or trgStartTr = '1') then
        cntBR <= conv_std_logic_vector(BR_Max, BR_Width);
        cntStat <= "1010";
      else
        if (trgBRZ = '1') then
          cntBR <= conv_std_logic_vector(BR_Max, BR_Width);
          if (fIdle = '0') then
            cntStat <= cntStat - '1';
          end if;
        else
          cntBR <= cntBR - '1';
        end if;
      end if;

      if (trgStartTr = '1') then
        fTr <= '1';
      elsif (fIdle = '1') then
        fTr <= '0';
      end if;

      -- write, sample & shift
      if (trgStartTr = '1') then
        sregBuf <= iData;
      elsif (fData = '1' and trgShift = '1') then
        sregBuf <= regRXD & sregBuf(7 downto 1);  -- right shift
      end if;
    end if;
  end process;
end rtl;
  1. 2006/06/29(木) 00:20:21|
  2. ハードウェア開発
  3. | トラックバック:0
  4. | コメント:0
<<[MAXII]hwSPXインターフェース完成。 | ホーム | [Brontes] 回路紹介>>

コメント

コメントの投稿


管理者にだけ表示を許可する

トラックバック

トラックバックURLはこちら
http://tm86eublog.blog42.fc2.com/tb.php/101-1bb30089
この記事にトラックバックする(FC2ブログユーザー)

来客数

プロフィール

Euphorie

Author:Euphorie
"おいふぉりー"って呼んでくださいな☆
ハードウェアとかソフトウェアとかの開発に興味があったり。。。
連絡先は上の画像。

最近の記事

最近のコメント

最近のトラックバック

月別アーカイブ

カテゴリー

ブロとも申請フォーム

この人とブロともになる

ブログ内検索

RSSフィード

リンク

このブログをリンクに追加する

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。