⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vdp_pack.vhd

📁 我自己写的vhdl程序
💻 VHD
📖 第 1 页 / 共 2 页
字号:
      SIGNAL dav      : OUT STD_LOGIC;
      SIGNAL hdb_busy : IN  STD_LOGIC
      ) IS

      VARIABLE cmdword : STD_LOGIC_VECTOR(15 DOWNTO 0);
      -- drive host bus with a new command
      -- wait until handshake is complete before returning
   BEGIN

      -- check parameters are legal
      ASSERT x >= 0 AND x < 64 AND y >= 0 AND y < 64 REPORT
         "Invalid parameters for send_vdp_command : x = " & i2s(x) &
         ", y = " & i2s(y)
         SEVERITY error;

      CASE cmd IS
         WHEN movepen     => cmdword(15 DOWNTO 14) := "00";
         WHEN drawline    => cmdword(15 DOWNTO 14) := "01";
         WHEN clearscreen => cmdword(15 DOWNTO 14) := "10";
         WHEN flushcache => cmdword(15 DOWNTO 14) := "11";
      END CASE;

      CASE pen IS
         WHEN black  => cmdword(1 DOWNTO 0) := "00";
         WHEN white  => cmdword(1 DOWNTO 0) := "01";
         WHEN invert => cmdword(1 DOWNTO 0) := "10";
      END CASE;

      cmdword(13 DOWNTO 8) := conv_std_logic_vector( x, 6);
      cmdword( 7 DOWNTO 2) := conv_std_logic_vector( y, 6);

      -- terminate last command if necessary
      ASSERT hdb_busy = '0' OR hdb_busy = '1' REPORT
         "hdb_busy (" & STD_LOGIC'IMAGE(hdb_busy) & " is not a valid value"
         SEVERITY error;
      IF hdb_busy /= '0' THEN
         WAIT UNTIL hdb_busy = '0';
      END IF;

      hdb <= cmdword;         -- put command on host bus
      dav <= '1';

      WAIT UNTIL hdb_busy = '1';  -- wait until data has been read

      dav <= '0';             -- host side of handshake is now complete
      WAIT FOR 0 ns;          -- make sure dav changes
   END send_vdp_command;


   ----------------------------------------------------------
   ------------- Software VDP  --------------------------------
   ----------------------------------------------------------


   PROCEDURE decode_paras(
      cmdword      : IN  STD_LOGIC_VECTOR(15 DOWNTO 0);
      VARIABLE cmd : OUT cmd_type;
      VARIABLE x   : OUT INTEGER;
      VARIABLE y   : OUT INTEGER;
      VARIABLE pen : OUT pen_type
      ) IS

   BEGIN
      CASE cmdword(15 DOWNTO 14) IS
         WHEN "00"   => cmd := movepen;
         WHEN "01"   => cmd := drawline;
         WHEN "10"   => cmd := clearscreen;
         WHEN "11"   => cmd := flushcache;
         WHEN OTHERS => REPORT "bad cmd field for do_command : " &
                           v2s(cmdword(15 DOWNTO 14));
      END CASE;


      CASE cmdword(1 DOWNTO 0) IS
         WHEN "00"   => pen := black;
         WHEN "01"   => pen := white;
         WHEN "10"   => pen := invert;
         WHEN OTHERS => REPORT "bad pen field for do_command : " &
                           v2s(cmdword(1 DOWNTO 0));
      END CASE;

      x := conv_integer(UNSIGNED(cmdword(13 DOWNTO 8)));
      y := conv_integer(UNSIGNED(cmdword(7 DOWNTO 2)));

   END PROCEDURE decode_paras;

   -- persistant state for do_command
   SHARED VARIABLE x_old : INTEGER RANGE 0 TO 63 := 0;
   SHARED VARIABLE y_old : INTEGER RANGE 0 TO 63 := 0;

   TYPE image_vector IS RECORD
                           x : INTEGER;
                           y : INTEGER;
                        END RECORD;





   PROCEDURE do_vdp_command(
      cmd               : IN  cmd_type;
      x                 : IN  INTEGER;
      y                 : IN  INTEGER;
      pen               : IN  pen_type;
      SIGNAL cycle_init : OUT STD_LOGIC;
      SIGNAL cycle_done : IN  STD_LOGIC;
      dest              : IN  ram_mode_type
      ) IS

      VARIABLE xt, yt : INTEGER;  -- temporary coordinates
      VARIABLE z      : INTEGER;  --temporary current perpendicular offset

      VARIABLE xa, xb, ya, yb, yinc : INTEGER;
      VARIABLE v1, v2, vdir, v      : image_vector;
      VARIABLE oct                  : STD_LOGIC_VECTOR( 0 TO 2);  -- bits determine octant


      PROCEDURE change_ram_bit(
         x                 : IN  INTEGER;
         y                 : IN  INTEGER;
         pen               : IN  pen_type;
         SIGNAL cycle_init : OUT STD_LOGIC;
         SIGNAL cycle_done : IN  STD_LOGIC;
         dest              : IN  ram_mode_type
         ) IS
         -- alters (x,y) pixel in image ram_array as specified by pen
         -- may need to read and write to ram_array (for invert writing)
         VARIABLE val : STD_LOGIC;  -- initial value in ram of bit to be written
      BEGIN
         CASE pen IS
            WHEN black  => write_ram_bit( x, y, '0', cycle_init, cycle_done, dest);
            WHEN white  => write_ram_bit( x, y, '1', cycle_init, cycle_done, dest);
            WHEN invert =>
               read_ram_bit(x, y, cycle_init, cycle_done, dest, val);
               write_ram_bit( x, y, NOT val, cycle_init, cycle_done, dest);
         END CASE;
      END change_ram_bit;

      FUNCTION cross(
         v1 : image_vector;
         v2 : image_vector
         ) RETURN INTEGER IS
         -- magnitude of v1 component in direction perpendicular to v2
      BEGIN
         RETURN v1.x*v2.y-v1.y*v2.x;
      END cross;

      PROCEDURE swap(
         -- sets big, small from a,b swapping if necessary so that big > small
         a              : IN  INTEGER;
         b              : IN  INTEGER;
         VARIABLE big   : OUT INTEGER;
         VARIABLE small : OUT INTEGER
         ) IS
      BEGIN
         big   := maximum(a, b);
         small := minimum(a, b);
      END swap;




   BEGIN
      -- implement the command by writing bits in ram
      CASE cmd IS
         WHEN movepen     => NULL;
         WHEN clearscreen =>
            swap( x, x_old, xb, xa);
            swap( y, y_old, yb, ya);
            --REPORT "clearing screen... xa=" & i2s(xa) &", xb="&i2s(xb)&
            --   ", ya="&i2s(ya)&", yb="&i2s(yb);
            -- xa<xb and ya<yb
            FOR i IN xa TO xb LOOP
               FOR j IN ya TO yb LOOP
                  change_ram_bit( i, j, pen, cycle_init, cycle_done, dest);
               END LOOP;
            END LOOP;
         -- flush cache does nothing in the behavioural VDP
         WHEN flushcache => NULL;
         WHEN drawline =>
            -- print out stuff for debugging 
            -- REPORT integer'image(x_old) & ", " & integer'image(y_old) & "   " &
            --     integer'image(x) & "," & integer'image(y);
            --
            -- swap coordinates so that we are always drawing line in direction
            -- of octant 1 or 2, 7 or 8 (ie x increasing)
            xt   := x_old;
            yt   := y_old;
            z    := 0;
            vdir := (x-x_old, y-y_old);  -- vector to draw
            FOR i IN 0 TO 2 LOOP
               oct(i) := '0';
            END LOOP;

            IF vdir.x > 0 THEN
               oct(0) := '1';
            END IF;

            IF vdir.y > 0 THEN
               oct(1) := '1';
            END IF;


            IF ABS(vdir.x) > ABS(vdir.y) THEN
               oct(2) := '1';
            END IF;
            CASE oct IS
               WHEN "111" => v1 := (1,1); v2 := (1,0);
               WHEN "110" => v1 := (0,1); v2 := (1,1);
               WHEN "010" => v1 := (-1,1); v2 := (0,1);
               WHEN "011" => v1 := (-1,0); v2 := (-1,1);
               WHEN "001" => v1 := (-1,-1); v2 := (-1,0);
               WHEN "000" => v1 := (0,-1); v2 := (-1,-1);
               WHEN "100" => v1 := (1,-1); v2 := (0,-1);
               WHEN "101" => v1 := (1,0); v2 := (1,-1);

               WHEN OTHERS => NULL;
            END CASE;


            -- implement line drawing algorithm

            WHILE NOT((xt = x) AND (yt = y)) LOOP
               -- this check should always pass
               ASSERT (ABS(xt) < 65) AND (ABS(yt) < 65)
                  REPORT "Overflow: xt=" & INTEGER'IMAGE(xt) & ", yt=" & INTEGER'IMAGE(yt) &
                  ", z=" & INTEGER'IMAGE(z) &
                  ", vdir=(" & INTEGER'IMAGE(vdir.x) & "," & INTEGER'IMAGE(vdir.y)& ")"
                  SEVERITY failure;
               
               change_ram_bit( xt, yt, pen, cycle_init, cycle_done, dest);
               IF ABS(z + cross( v1, vdir)) < ABS(z+cross(v2, vdir)) THEN
                  v := v1;
               ELSE
                  v := v2;
               END IF;
               xt := xt+v.x; yt := yt+v.y;
               z  := z + cross( v, vdir);
            END LOOP;
            -- set last pixel
            change_ram_bit( xt, yt, pen, cycle_init, cycle_done, dest);
      END CASE;
      -- tidy up setting old coords to new
      x_old := x;
      y_old := y;
      -- finished!    
   END do_vdp_command;


   PROCEDURE write_lines(fname : IN STRING) IS

      -- writes out a sequence of commands to a file with filename fname
      -- the commands draw a star pattern on the screen, including lines
      -- in every possible octant, and every octant boundary
      -- The file can be read, and run through the behavioural VDP
      -- using vdp_testbench.

      CONSTANT r       : INTEGER := 10;
      CONSTANT xcentre : INTEGER := 32;
      CONSTANT ycentre : INTEGER := 32;

      FILE f : TEXT OPEN write_mode IS fname;

      VARIABLE buf : LINE;

   BEGIN

      FOR i IN -2 TO 2 LOOP
         FOR j IN -2 TO 2 LOOP
            IF ABS(i) = 2 OR ABS(j) = 2 THEN

               write( buf, STRING'("MB "));
               write( buf, xcentre+r*i);
               write( buf, STRING'(" "));
               write( buf, ycentre+r*j);
               writeline(f, buf);

               write( buf, STRING'("DB "));
               write( buf, xcentre);
               write( buf, STRING'(" "));
               write( buf, ycentre);
               writeline(f, buf);
            END IF;
         END LOOP;
      END LOOP;
   END write_lines;





-- this runs a set of commands from file fname through a behavioural
-- VDP which writes to ram using do_ram_cycle, with destination ram_data_model
   PROCEDURE run_command_file(
      fname             : IN  STRING;
      SIGNAL cycle_init : OUT STD_LOGIC;
      SIGNAL cycle_done : IN  STD_LOGIC
      ) IS

      FILE f            : TEXT OPEN read_mode IS fname;
      VARIABLE buf      : LINE;
      VARIABLE ch       : CHARACTER;
      VARIABLE cmd      : cmd_type;
      VARIABLE pen      : pen_type;
      VARIABLE x, y     : INTEGER;
      VARIABLE n        : INTEGER;
      VARIABLE skipline : BOOLEAN;
      
   BEGIN
      n := 1;

      WHILE NOT endfile(f) LOOP
         readline( f, buf);
         read( buf, ch);
         skipline := false;
         CASE ch IS
            WHEN 'D'    => cmd      := drawline;
            WHEN 'M'    => cmd      := movepen;
            WHEN 'C'    => cmd      := clearscreen;
            WHEN 'F'    => cmd      := flushcache;
            WHEN '-'    => skipline := true;
            WHEN OTHERS =>
               REPORT "Bad character ("& ch &
                  ") should be [DMC] in col 1, line "&i2s(n);
         END CASE;
         IF NOT skipline THEN
            read( buf, ch);
            CASE ch IS
               WHEN 'B'    => pen := black;
               WHEN 'W'    => pen := white;
               WHEN 'I'    => pen := invert;
               WHEN OTHERS =>
                  REPORT "Bad character ("& ch &
                     ") should be [BWI] in col 2, line "&i2s(n);
            END CASE;

            read( buf, x);
            read( buf, y);
            do_vdp_command(cmd, x, y, pen, cycle_init, cycle_done, model);
         END IF;

         n := n+1;
      END LOOP;
      
   END run_command_file;


END vdp_pack;


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -