<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>G33K @ Work &#187; Xilinx</title>
	<atom:link href="http://www.geekatwork.de/tag/xilinx/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.geekatwork.de</link>
	<description>Basteleien eines Geeks</description>
	<lastBuildDate>Mon, 12 Jul 2010 08:38:54 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>I can haz FPGA?</title>
		<link>http://www.geekatwork.de/2010/01/17/i-can-haz-fpga/</link>
		<comments>http://www.geekatwork.de/2010/01/17/i-can-haz-fpga/#comments</comments>
		<pubDate>Sun, 17 Jan 2010 21:23:30 +0000</pubDate>
		<dc:creator>Andy</dc:creator>
				<category><![CDATA[Elektronik]]></category>
		<category><![CDATA[FPGA]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Xilinx]]></category>

		<guid isPermaLink="false">http://www.geekatwork.de/?p=89</guid>
		<description><![CDATA[Da ises weg, das Weihnachtsgeld.

Draufgegangen ist d [...]]]></description>
			<content:encoded><![CDATA[<p>Da ises weg, das Weihnachtsgeld.</p>
<p>Draufgegangen ist das unter anderem für dieses hübsche, aber leider teure FPGA-Board mit einem Xilinx Spartan 3 FPGA:<br />
<a href="http://www.geekatwork.de/wp-content/uploads/2010-01-12-23.48.01-e1263764275949.jpg" rel="lightbox"><img class="alignnone size-medium wp-image-90" title="spartan3an" src="http://www.geekatwork.de/wp-content/uploads/2010-01-12-23.48.01-300x225.jpg" alt="" width="300" height="225" /></a></p>
<p><span id="more-89"></span>Wie man sieht, sieht man ein A auf dem LCD Display. Viel mehr habe ich damit noch nicht zustande gebracht. Besonders einfach wirds einem aber sowieso nicht gemacht. Das Ding ist halt kein Prozessor, mit dem man sequentielle Abläufe durch das Ausführen eines Programms abbilden kann, sondern pure Digitaltechnik.<br />
Durch VHDL wird einem das Beschreiben etwas einfacher gemacht, die Vorgänge laufen aber alle parallel in diesem Chip ab. Signale warten nicht einfach so auf ein Ereignis.</p>
<p>Signalabläufe wie sie von einem Displaycontroller erwartet werden können auch nur über eine Statemachine modelliert werden. Man hüpft also von einem Zustand in den anderen und legt die passenden Signale an die Leitungen. Danach springt man meistens wieder in eine Warteschleife, weil der LCD-Controller üblicherweise langsamer ist als so ein FPGA.</p>
<p>Da man das ganze äußerst schlecht debuggen kann, simuliert man im Vorfeld die Abläufe. Man schreibt also erstmal sein Modul in VHDL und darf sich dann auch noch darum kümmern einen Sogenannten Testbench zu schreiben. Dieser Testbench ist dann dafür zuständig die passenden Signale, die normalerweise durch externe Quellen erzeugt werden, an das Modul zu legen, um das alles in Software abbilden zu können.</p>
<p>Nachdem man dann die Simulation für einige Milisekunden ausgeführt hat, sieht das so aus:<br />
<a href="http://www.geekatwork.de/wp-content/uploads/rs232_wave.png" rel="lightbox"><img class="alignnone size-medium wp-image-91" title="RS232 Simulation" src="http://www.geekatwork.de/wp-content/uploads/rs232_wave-300x101.png" alt="" width="300" height="101" /></a></p>
<p>Auf diesem Bild sieht man die Simulation eines RS232 Moduls. Die Länge eines Bits ist hier 8,6µs, was eine Baudrate von 115200 pro Sekunde ergibt.<br />
Als erstes wird in tx_data das Byte abgelegt, welches üertragen werden soll. Dann zieht man tx_start kurz auf High, was man hier nicht sieht, da es bereits 40ns nach dem Start passiert, und die Übertragung startet. Erst kommt das Startbit auf der TXD-Leitung, dann eine 0, dann eine 1 usw. bis das Stopbit kommt und die Leitung wieder auf &#8220;Standby&#8221; geht und somit 0xAA übertragen wurde. RS232 überträgt das niederwertigste Bit zuerst.</p>
<p>Analog läuft das mit dem Empfangen ab.</p>
<p>In VHDL sieht das ganze dann so aus:</p>
<pre class="brush:plain">library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

entity RS232 is
    Generic ( Clockrate : integer   := 50000000;  -- Hertz
              Baudrate  : integer   :=  9600      -- Bits/Sec
             );
    Port ( RXD      : in   STD_LOGIC;
           RX_Data  : out  STD_LOGIC_VECTOR (7 downto 0);
           RX_Busy  : out  STD_LOGIC;
           TXD      : out  STD_LOGIC;
           TX_Data  : in   STD_LOGIC_VECTOR (7 downto 0);
           TX_Start : in   STD_LOGIC;
           TX_Busy  : out  STD_LOGIC;
           CLK      : in   STD_LOGIC
           );
end RS232;

architecture Behavioral of RS232 is
signal txstart : std_logic := '0';
signal txsr    : std_logic_vector  (9 downto 0) := "1111111111";
signal txbitcnt : integer range 0 to 10 := 10;
signal txcnt    : integer range 0 to (Clockrate/Baudrate)-1;

signal rxd_sr  : std_logic_vector (3 downto 0) := "1111";
signal rxsr    : std_logic_vector (7 downto 0) := "00000000";
signal rxbitcnt : integer range 0 to 9 := 9;
signal rxcnt   : integer range 0 to (Clockrate/Baudrate)-1; 

begin
   send: process(CLK)
   begin
      if rising_edge(CLK) then
         txstart &lt;= TX_Start;
         if (TX_Start = '1' and txstart = '0') then
            txcnt    &lt;= 0;
            txbitcnt &lt;= 0;
            txsr     &lt;= '1' &amp; TX_Data &amp; '0';
         else
            if(txcnt&lt;(Clockrate/Baudrate)-1) then
               txcnt &lt;= txcnt + 1;
            else
               if (txbitcnt &lt; 10) then
                  txcnt    &lt;= 0;
                  txbitcnt &lt;= txbitcnt + 1;
                  txsr     &lt;= '1' &amp; txsr(txsr'left downto 1);
               end if;
            end if;
         end if;
      end if;
   end process;
   TXD     &lt;= txsr(0);
   TX_Busy &lt;= '1' when (txbitcnt &lt; 10) else '0';

   receive: process(CLK)
   begin
      if rising_edge(CLK) then
         rxd_sr &lt;= rxd_sr(rxd_sr'left - 1 downto 0) &amp; RXD;
         if (rxbitcnt &lt; 9) then
            if(rxcnt &lt; (Clockrate / Baudrate) - 1) then
               rxcnt    &lt;= rxcnt + 1;
            else
               rxcnt    &lt;= 0;
               rxbitcnt &lt;= rxbitcnt + 1;
               rxsr     &lt;= rxd_sr(rxd_sr'left - 1) &amp; rxsr(rxsr'left downto 1);
            end if;
         else
            if (rxd_sr(3 downto 2) = "10") then
               rxcnt    &lt;= ((Clockrate / Baudrate) - 1) / 2;
               rxbitcnt &lt;= 0;
            end if;
         end if;
      end if;
   end process;
   RX_Data &lt;= rxsr;
   RX_Busy &lt;= '1' when (rxbitcnt &lt; 9) else '0';

end Behavioral;</pre>
<p>Mit einer &#8220;entity&#8221; beschreibt man, dass es irgendein Modul mit entsprechendem Namen gibt und welche Leitungen da rein und rausgehen.<br />
Im &#8220;Behaviour&#8221; beschreibt man dann, wie sich das Modul verhält und welche internen Signale oder Variablen es gibt. Wir haben in diesem Fall 2 Prozesse. Einen zum Senden und einen zum Emmpfangen. Jeder dieser Prozesse kann gleichzeitig ausgeführt werden.</p>
<p>Der passende Testbench zu diesem RS232 Modul sieht dann so aus:</p>
<pre class="brush:plain">LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.std_logic_unsigned.all;
USE ieee.numeric_std.ALL;

ENTITY rs232_tb IS
END rs232_tb;

ARCHITECTURE behavior OF rs232_tb IS 

    -- Component Declaration for the Unit Under Test (UUT)

    COMPONENT RS232
   GENERIC ( Clockrate : integer := 50000000;
             Baudrate : integer := 115200);
    PORT(
         RXD : IN  std_logic;
         RX_Data : OUT  std_logic_vector(7 downto 0);
         RX_Busy : OUT  std_logic;
         TXD : OUT  std_logic;
         TX_Data : IN  std_logic_vector(7 downto 0);
         TX_Start : IN  std_logic;
         TX_Busy : OUT  std_logic;
         CLK : IN  std_logic
        );
    END COMPONENT;

   --Inputs
   signal RXD : std_logic := '0';
   signal TX_Data : std_logic_vector(7 downto 0) := (others =&gt; '0');
   signal TX_Start : std_logic := '0';
   signal CLK : std_logic := '0';

   --Outputs
   signal RX_Data : std_logic_vector(7 downto 0);
   signal RX_Busy : std_logic;
   signal TXD : std_logic;
   signal TX_Busy : std_logic;

  constant clk_period : time := 20 ns;

BEGIN

  -- Instantiate the Unit Under Test (UUT)
   uut: RS232 PORT MAP (
          RXD =&gt; RXD,
          RX_Data =&gt; RX_Data,
          RX_Busy =&gt; RX_Busy,
          TXD =&gt; TXD,
          TX_Data =&gt; TX_Data,
          TX_Start =&gt; TX_Start,
          TX_Busy =&gt; TX_Busy,
          CLK =&gt; CLK
        );

   clk_process :process
   begin
      CLK &lt;= '0';
      wait for clk_period/2;
      CLK &lt;= '1';
      wait for clk_period/2;
   end process;

   -- Stimulus process
   stim_proc: process
   begin
      RXD &lt;= '1';            --idle
      wait for clk_period*2;

      TX_Data &lt;= "10101010";
      TX_Start &lt;= '1';

      wait for clk_period*5;
      TX_Start &lt;= '0';

      wait for clk_period*5000;

      --startbit
      RXD &lt;= '0';
      --435 clock cycles by 20ns each = 8,7us = length of bit with 115200 baud
      wait for clk_period*435;

      RXD &lt;= '0';
      wait for clk_period*435;
      RXD &lt;= '1';
      wait for clk_period*435;
      RXD &lt;= '0';
      wait for clk_period*435;
      RXD &lt;= '1';
      wait for clk_period*435;
      RXD &lt;= '0';
      wait for clk_period*435;
      RXD &lt;= '1';
      wait for clk_period*435;
      RXD &lt;= '0';
      wait for clk_period*435;
      RXD &lt;= '1';
      wait for clk_period*435;

      --stopbit and idle
      RXD &lt;= '1';

      wait;
   end process;

end;</pre>
<p>Der Aufbau ist ähnlich wie vorhin. Die Entity hier enthält jedoch keine Ein- oder Ausgabesignale, da hier später nur die internen Signale dieses Testbenches im Simulator betrachtet werden. Natürlich kann man später in der Waveform noch weitere Signale hinzufügen. Zum Beispiel interne Signale aus dem getesteten Modul.<br />
Im Behaviour wird dann als erses die Komponente RS232 definiert. Es gibt also irgendwo ein solches Modul, das später hier genutzt werden kann. Darauf folgend kommen wieder einige Signale, denen man später in Prozessen Werte zuweisen kann oder von denen man Werte auf den Leitungen abgreifen kann.<br />
Danach wird ein RS232 Modul mit dem Namen uut (&#8220;unit under test&#8221;) instanziert und die Ports des Moduls werden mit den internen Signalen verknüpft.<br />
Dann folgen wieder Prozesse. Der erste generiert das Clocksignal und der zweite ist für den eigentlichen Ablauf des Test verantwortlich. Das Senden ist hier relativ einfach: Wert in tx_data schreiben, für kurze Zeit an tx_start ziehen und dann beginnt die Übertragung.</p>
<p>Der Empfangstest ist dahingehend schwieriger, dass jedes Bit für eine bestimmte Zeit anliegen muss, wie es in Wirklichkeit auf einem Kabel auch der Fall wäre.<br />
clk_period*435 entspricht hier exakt 8,7µs, was wiederrum ungefähr 115200 Baud/s entspricht: 20ns*435 = 8700ns = 8,7µs</p>
<p>Als nächstes werde ich mich mal an den VGA Ausgang setzen und probieren ein Bild zu zaubern. Danach ist allerdings auch schon der DDR2-Speichercontroller dran: Für ein 12 Bit VGA-Bild bei einer Auflösung von 640&#215;480 Pixeln sind schon 450KB Video RAM nötig. Mit double buffering sind wir dann bei 900KB.</p>
<p><strong>Update:</strong> Das RS232 Modul stammt im übrigen von <a href="http://www.lothar-miller.de/s9y/categories/42-RS232" target="_blank">hier</a>. Lediglich den Testbench habe ich mir dann noch dazugeschrieben.</p>
 <p>Feel free to Flattr this post at <a href="http://flattr.com/" title="Flattr" target="_blank">flattr.com</a>, if you like it.</p> <p><a href="http://flattr.com/" title="Flattr" target="_blank"><img src="http://www.geekatwork.de/wp-content/plugins/flattrss/button-compact-static-100x17.png" alt="flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.geekatwork.de/2010/01/17/i-can-haz-fpga/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
