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

📄 vgachr 8080.v

📁 code guide to design cpu 8080
💻 V
📖 第 1 页 / 共 5 页
字号:
               wrtchr <= 0; // remove ready to write
               outrdy <= 1; // set ready to send
               state <= `term_idle;

            end

         end
      
         default: state <= 6'bx;
      
      endcase

   end
      
   // Enable drive to character memory
   assign cmdata = cmdatae ? cmdatai: 8'bz;

   // Enable drive to character attributes
   assign cmattr = cmattre ? cmattri: 8'bz;

   // Enable drive for data output
   assign data = read&select ? datao: 8'bz;

endmodule

////////////////////////////////////////////////////////////////////////////////
//
// MEMORY MAPPED CHARACTER DISPLAY
//
// Contains the 20x8 characters used in a 640x480, 24 lines of 80 characters
// display. This display is accessed vi a 1920 character memory, which can be 
// written and read. It is dual port, so has no restrictions on read and write.
//
// This block can either be directly mapped to CPU main memory, or can be run
// via a terminal emulator.
//
// Note there wasn't a mode for 24 lines, or for 640x480 pixels for alpha mode
// on the PC. Instead, 640x480 was a standard VGA mode for graphics. I like it
// because it unifies graphics and alpha modes, and has even divisions to
// character cells. Its a bit difficult to fit characters into a 8x20 cell,
// but the modes used for alpha, like 640x400 or 640x300 are not 4:3 aspect
// ratios, and really work by stretching the pixels vertically. We just do
// the same thing by explicit mapping.
//

`define clkfreq   50000000              // input clock frequency
`define blinkfreq 1                     // blink cycle in seconds
`define blinkmax  (`clkfreq*`blinkfreq) // total blink cycle

module chrmemmap(rst_n, clk, r, g, b, hsync_n, vsync_n, addr, read, write, 
                 data, attr, cursor);

      input         rst_n;   // reset
      input         clk;     // master clock
      output [2:0]  r, g, b; // R,G,B color output buses
      output        hsync_n; // horizontal sync pulse
      output        vsync_n; // vertical sync pulse
      input  [10:0] addr;    // address to read or write
      input         read;    // read from address
      input         write;   // write from address
      inout  [7:0]  data;    // data to be written/read
      inout  [4:0]  attr;    // attributes to be written/read
      input [10:0]  cursor;  // cursor address

   reg [15:0] pixeldata; // 16 bit pixel feed

   reg  [6:0]  chrcnt;   // character counter
   reg  [4:0]  rowcnt;   // character row counter
   reg  [4:0]  lincnt;   // line counter
   reg  [10:0] scnadr;   // screen character buffer address
   reg  [7:0]  curchr;   // current character indexed by scnadr
   reg  [4:0]  curatr;   // current attribute indexed by scnadr
   reg  [1:0]  fchsta;   // character fetch state, 0 = load high, 1 = load low
   wire [10:0] chradr;   // character generator address
   wire [7:0]  chrdata;  // character generator data
   reg  [7:0]  datao;    // intermediate for data output
   reg  [4:0]  attro;    // intermediate for attribute output
   reg  [7:0]  pixdatl;  // pixel data low holding
   reg  [31:0] blinkcnt; // blink cycle counter
   reg         blon;     // blink on/off

   // storage for character based screen

   reg [7:0] scnbuf[1919:0]; // screen
   reg [4:0] atrbuf[1919:0]; // attributes

   assign rst = ~rst_n; // change reset polarity

   vga vgai(.rst(rst), .clk(clk), .pixel_data_in(pixeldata), .rd(rd), .eof(eof),
            .r(r), .g(g), .b(b), .hsync_n(hsync_n), .vsync_n(vsync_n), 
            .blank(blank));

   chrrom crom(chradr, chrdata); // place character generator

   // run the blink cycle counter
   always @(posedge clk)
      if (rst) begin

      blinkcnt <= 0; // clear blink cycle
      blon <= 0; // clear cursor blink on

   end else begin

      blinkcnt <= blinkcnt+1; // count blink cycle
      // check blink cycle maxed, recycle if so
      if (blinkcnt >= `blinkmax) begin

         blinkcnt <= 0; // clear blink count
         blon <= ~blon; // flip blink state

      end

   end

   // run the character to screen scan
   always @(posedge clk)
      if (rst) begin // if reset

      // ????? SIMULATION PLUG
      // starting the character counter at the end of the line allows the scan
      // to cross the area the CPU is filling, and is ok at hardware time.
      // chrcnt <= 7'h0; // clear counters
      chrcnt <= 80-20; // clear counters
      // ????? SIMULATION PLUG
      // Starting the row count at 1 allows pixels to appear on the simulation,
      // and produces only a single bad line in real hardware
      rowcnt <= 5'h0;
      // rowcnt <= 5'h1;
      lincnt <= 5'h0;
      scnadr <= 11'h0;
      fchsta <= 0;

   end else if (eof) begin // if end of frame

      chrcnt <= 7'h0; // clear counters
      rowcnt <= 5'h0;
      lincnt <= 5'h0;
      scnadr <= 11'h0;
      fchsta <= 1; // set to fetch first set of characters

   end else if (rd || fchsta) begin

      if (fchsta == 1 || fchsta == 3) begin

         // advance counters
         if (chrcnt < 79) chrcnt <= chrcnt+1; // next character count
         else begin // next row
      
            chrcnt <= 0; // reset character
            if (rowcnt < 19) rowcnt <= rowcnt+1; // next character row
            else begin // next line
      
               rowcnt <= 0; // reset row
               lincnt <= lincnt+1; // next line
               scnadr <= scnadr+80; // advance character fetch
      
            end
      
         end

      end

      // Choose high or low character, and next state. Note we have to flip the
      // characters left to right to be correct.
      case (fchsta)

         0: fchsta <= 1; // delay until rd cycle is over

         1: begin
   
            // Set low bits of pixel register, and reverse if cursor matches the
            // current position, or if reverse attribute is on. Turn it all off
            // if blank is on.
            if ((scnadr+chrcnt == cursor)^curatr[2])
               pixdatl <= ~(curatr[0]|(curatr[1]&blon)? 8'h00: // blink and blank
                             (curatr[3]&rowcnt == 14? 8'hff: // underline 
                              { chrdata[0], chrdata[1], chrdata[2], chrdata[3],
                                chrdata[4], chrdata[5], chrdata[6], chrdata[7] }));
            else 
               pixdatl <= curatr[0]|(curatr[1]&blon)? 8'h00: // blink and blank
                             (curatr[3]&rowcnt == 14? 8'hff: // underline 
                              { chrdata[0], chrdata[1], chrdata[2], chrdata[3],
                                chrdata[4], chrdata[5], chrdata[6], chrdata[7] });
            fchsta <= 2; // next state
   
         end

         2: fchsta <= 3; // delay a cycle for ROM read time

         3: begin
   
            // Set low bits of pixel register, and reverse if cursor matches the
            // current position, or if reverse attribute is on. Turn it all off
            // if blank is on.
            if ((scnadr+chrcnt == cursor)^curatr[2]) 
               pixeldata <= pixdatl |
                 (~(curatr[0]|(curatr[1]&blon)? 8'h00: // blink and blank
                    (curatr[3]&rowcnt == 14? 8'hff: // underline 
                     { chrdata[0], chrdata[1], chrdata[2], chrdata[3],
                       chrdata[4], chrdata[5], chrdata[6], chrdata[7] })) & 
                  8'hff) << 8;
            else 
               pixeldata <= pixdatl |
                 (curatr[0]|(curatr[1]&blon)? 8'h00: // blink and blank
                    (curatr[3]&rowcnt == 14? 8'hff: // underline 
                     { chrdata[0], chrdata[1], chrdata[2], chrdata[3],
                       chrdata[4], chrdata[5], chrdata[6], chrdata[7] })) << 8;
            fchsta <= 0; // back to start
            
         end
   
      endcase

   end

   // operate dual port screen character RAM
   always @(posedge clk) begin

      // set current indexed character without parity
      curchr <= scnbuf[scnadr+chrcnt] & 8'h7f;
      if (write) scnbuf[addr] <= data;
      datao <= scnbuf[addr];

   end

   // operate dual port screen attribute RAM
   always @(posedge clk) begin

      // set current indexed character without parity
      curatr <= atrbuf[scnadr+chrcnt];
      if (write) atrbuf[addr] <= attr;
      attro <= atrbuf[addr];

   end

   // create character address from character in buffer and current row
   assign chradr =
      (curchr < 8'h20 || curchr == 8'h7f) ? 11'h0: (curchr-8'h20)*20+rowcnt;

   // Enable drive for data output
   assign data = read ? datao: 8'bz;
   assign attr = read ? attro: 8'bz;

endmodule

////////////////////////////////////////////////////////////////////////////////
//
// CHARACTER ROM
//
// Contains the 20x8 characters used in a 640x480, 25 lines of 80 characters
// display.
//

module chrrom(addr, data);

   input  [10:0] addr;
   output [7:0]  data;

   reg [7:0]  data;

   always @(addr) case (addr)

      // Character set starting with space, and ending with '~'

      // The design of characters is such that they are embedded into an odd
      // number of pixels, 7x19, with one space pixel to the right and bottom
      // of each cell. The character layout works best on an odd cell width
      // and height, because this gives a clear center to the character.
      // Each characters baseline is marked. The baseline is where the capital
      // characters sit, and only the descenders go below this position.

      11'h000: data = 8'b00000000; // ' '
      11'h001: data = 8'b00000000;
      11'h002: data = 8'b00000000;
      11'h003: data = 8'b00000000;
      11'h004: data = 8'b00000000;
      11'h005: data = 8'b00000000;
      11'h006: data = 8'b00000000;
      11'h007: data = 8'b00000000;
      11'h008: data = 8'b00000000;
      11'h009: data = 8'b00000000;
      11'h00A: data = 8'b00000000;
      11'h00B: data = 8'b00000000;
      11'h00C: data = 8'b00000000; // B
      11'h00D: data = 8'b00000000;
      11'h00E: data = 8'b00000000;
      11'h00F: data = 8'b00000000;
      11'h010: data = 8'b00000000;
      11'h011: data = 8'b00000000;
      11'h012: data = 8'b00000000;
      11'h013: data = 8'b00000000;

      11'h014: data = 8'b00010000; // '!'
      11'h015: data = 8'b00010000;
      11'h016: data = 8'b00010000;
      11'h017: data = 8'b00010000;
      11'h018: data = 8'b00010000;
      11'h019: data = 8'b00010000;
      11'h01A: data = 8'b00010000;
      11'h01B: data = 8'b00010000;
      11'h01C: data = 8'b00010000;
      11'h01D: data = 8'b00010000;
      11'h01E: data = 8'b00000000;
      11'h01F: data = 8'b00010000;
      11'h020: data = 8'b00010000; // B
      11'h021: data = 8'b00000000;     
      11'h022: data = 8'b00000000;
      11'h023: data = 8'b00000000;  
      11'h024: data = 8'b00000000;
      11'h025: data = 8'b00000000;
      11'h026: data = 8'b00000000;
      11'h027: data = 8'b00000000;

      11'h028: data = 8'b00000000; // '"'
      11'h029: data = 8'b00101000;
      11'h02A: data = 8'b00101000;
      11'h02B: data = 8'b00000000;
      11'h02C: data = 8'b00000000;
      11'h02D: data = 8'b00000000;
      11'h02E: data = 8'b00000000;
      11'h02F: data = 8'b00000000;
      11'h030: data = 8'b00000000;
      11'h031: data = 8'b00000000;
      11'h032: data = 8'b00000000;
      11'h033: data = 8'b00000000;
      11'h034: data = 8'b00000000; // B
      11'h035: data = 8'b00000000;     
      11'h036: data = 8'b00000000;
      11'h037: data = 8'b00000000;
      11'h038: data = 8'b00000000;
      11'h039: data = 8'b00000000;
      11'h03A: data = 8'b00000000;
      11'h03B: data = 8'b00000000;

      11'h03C: data = 8'b01000100; // '#'
      11'h03D: data = 8'b01000100;
      11'h03E: data = 8'b01000100;
      11'h03F: data = 8'b01000100;
      11'h040: data = 8'b11111110;
      11'h041: data = 8'b01000100;
      11'h042: data = 8'b01000100;
      11'h043: data = 8'b01000100;
      11'h044: data = 8'b11111110;
      11'h045: data = 8'b01000100;
      11'h046: data = 8'b01000100;
      11'h047: data = 8'b01000100;
      11'h048: data = 8'b01000100; // B
      11'h049: data = 8'b00000000;     
      11'h04A: data = 8'b00000000;
      11'h04B: data = 8'b00000000;
      11'h04C: data = 8'b00000000;
      11'h04D: data = 8'b00000000;
      11'h04E: data = 8'b00000000;
      11'h04F: data = 8'b00000000;

⌨️ 快捷键说明

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