• 使用system verilog进行流水灯和VGA打印字符


    使用system verilog进行流水灯和VGA打印字符

    system verilog的优点

    面向对象编程:SystemVerilog 引入了面向对象的编程特性,如类(class)和继承,这有助于创建可重用的代码和设计模式。

    增强的验证能力:SystemVerilog 支持断言(assertions)和覆盖率(coverage)分析,这些是验证复杂设计的关键工具。

    并发建模:SystemVerilog 允许更自然地建模并发事件,通过使用 fork-join 语句来创建并行线程。

    更丰富的数据类型:SystemVerilog 增加了多种数据类型,例如枚举(enum)、结构体(struct)、联合体(union)和数组,这些使得数据建模更加灵活和强大。

    参数化编程:通过宏和参数化编程,SystemVerilog 允许更灵活的设计,可以更容易地创建可配置和可重用的设计组件。

    改善的模块间连接:SystemVerilog 引入了接口(interface)的概念,简化了模块间的连接,并使得设计更加模块化。

    更高级的建模能力:SystemVerilog 支持更高层次的抽象建模,有助于设计者在系统级别进行设计和验证。

    随机化测试:SystemVerilog 支持随机化测试,可以自动生成测试向量,这有助于更全面地验证设计。

    更有效的代码复用:通过封装和模块化,SystemVerilog 促进了代码的复用,提高了设计效率。

    标准和兼容性:SystemVerilog 作为 IEEE 标准的一部分,确保了设计和验证方法的兼容性和标准化。

    VGA程序编写

    VGA 控制器模块

    首先是 VGA 控制器模块,负责生成 VGA 信号和像素坐标。

    module VGAController (
      input logic clk,      // 时钟
      input logic reset,    // 复位
      output logic hsync,   // 水平同步信号
      output logic vsync,   // 垂直同步信号
      output logic [9:0] pixelX,  // 像素 X 坐标
      output logic [9:0] pixelY,  // 像素 Y 坐标
      output logic displayOn       // 是否显示像素
    );
      // VGA 时序参数
      parameter H_VISIBLE_AREA = 640;
      parameter H_FRONT_PORCH = 16;
      parameter H_SYNC_PULSE = 96;
      parameter H_BACK_PORCH = 48;
      parameter H_TOTAL = H_VISIBLE_AREA + H_FRONT_PORCH + H_SYNC_PULSE + H_BACK_PORCH;
    
      parameter V_VISIBLE_AREA = 480;
      parameter V_FRONT_PORCH = 10;
      parameter V_SYNC_PULSE = 2;
      parameter V_BACK_PORCH = 33;
      parameter V_TOTAL = V_VISIBLE_AREA + V_FRONT_PORCH + V_SYNC_PULSE + V_BACK_PORCH;
    
      // 水平和垂直计数器
      logic [9:0] hCounter;
      logic [9:0] vCounter;
    
      // 水平计数器更新
      always_ff @(posedge clk or posedge reset) begin
        if (reset) begin
          hCounter <= 0;
          vCounter <= 0;
        end else begin
          if (hCounter == H_TOTAL - 1) begin
            hCounter <= 0;
            if (vCounter == V_TOTAL - 1) begin
              vCounter <= 0;
            end else begin
              vCounter <= vCounter + 1;
            end
          end else begin
            hCounter <= hCounter + 1;
          end
        end
      end
    
      // 生成同步信号
      assign hsync = !(hCounter >= H_VISIBLE_AREA + H_FRONT_PORCH && hCounter < H_VISIBLE_AREA + H_FRONT_PORCH + H_SYNC_PULSE);
      assign vsync = !(vCounter >= V_VISIBLE_AREA + V_FRONT_PORCH && vCounter < V_VISIBLE_AREA + V_FRONT_PORCH + V_SYNC_PULSE);
    
      // 输出像素坐标和显示信号
      assign pixelX = hCounter;
      assign pixelY = vCounter;
      assign displayOn = (hCounter < H_VISIBLE_AREA) && (vCounter < V_VISIBLE_AREA);
    endmodule
    

    字符生成模块

    接下来是字符生成模块,根据像素坐标生成 “你好FPGA” 字符。

    module CharGen (
      input logic clk,          // 时钟
      input logic reset,        // 复位
      input logic [9:0] pixelX, // 像素 X 坐标
      input logic [9:0] pixelY, // 像素 Y 坐标
      input logic displayOn,    // 是否显示像素
      output logic [3:0] red,   // 红色分量
      output logic [3:0] green, // 绿色分量
      output logic [3:0] blue   // 蓝色分量
    );
      // 字符映射表,可以通过像素坐标获取相应的像素值
      reg [63:0] charMap [0:6] = '{64'h7C121212127C00, 64'h42427E424200, 64'h7E0909090000, 64'h7E0909090600, 64'h3E414949493200, 64'h7E09097E0000, 64'h00000000000000};
    
      // 计算字符索引和像素在字符中的位置
      reg [3:0] charIndex;
      reg [2:0] charRow, charCol;
      reg [2:0] pixelXInChar, pixelYInChar;
      reg charPixel;
    
      always_ff @(posedge clk or posedge reset) begin
        if (reset) begin
          charIndex <= 0;
          charRow <= 0;
          charCol <= 0;
          pixelXInChar <= 0;
          pixelYInChar <= 0;
          charPixel <= 0;
        end else begin
          // 计算当前字符索引
          charCol <= pixelX / 8;
          charRow <= pixelY / 12;
          charIndex <= charCol + (charRow * 8);
    
          // 计算像素在字符中的位置
          pixelXInChar <= pixelX % 8;
          pixelYInChar <= pixelY % 12;
    
          // 获取当前像素值
          charPixel <= (charMap[charIndex])[63 - (pixelYInChar * 8 + pixelXInChar)];
        end
      end
    
      // 生成 RGB 信号
      always_comb begin
        case (charPixel)
          1'b0: begin
            red = 4'h0;
            green = 4'h0;
            blue = 4'h0;
          end
          1'b1: begin
            red = 4'hF;
            green = 4'hF;
            blue = 4'hF;
          end
          default: begin
            red = 4'h0;
            green = 4'h0;
            blue = 4'h0;
          end
        endcase
      end
    endmodule
    

    顶层模块

    以下是顶层模块,将 VGA 控制器和字符生成模块结合在一起,并输出到开发板上。

    module Top (
      input logic clk,   // 时钟
      input logic reset, // 复位
      output logic [3:0] red,     // 红色信号
      output logic [3:0] green,   // 绿色信号
      output logic [3:0] blue,    // 蓝色信号
      output logic hsync,         // 水平同步信号
      output logic vsync          // 垂直同步信号
    );
      // 实例化 VGA 控制器和字符生成模块
      VGAController vgaController (
        .clk(clk),
        .reset(reset),
        .hsync(hsync),
        .vsync(vsync),
        .pixelX(pixelX),
        .pixelY(pixelY),
        .displayOn(displayOn)
      );
    
      CharGen charGen (
        .clk(clk),
        .reset(reset),
        .pixelX(pixelX),
        .pixelY(pixelY),
        .displayOn(displayOn),
        .red(red),
        .green(green),
        .blue(blue)
      );
    
    endmodule
    

    测试基准程序

    最后是测试基准程序,用于测试顶层模块的功能。

    module Top_tb;
    
      // 时钟和复位信号
      logic clk;
      logic reset;
    
      // VGA 控制器和字符生成模块的信号
      logic hsync;
      logic vsync;
      logic [9:0] pixelX;
      logic [9:0] pixelY;
      logic displayOn;
      logic [3:0] red;
      logic [3:0] green;
      logic [3:0] blue;
    
      // 实例化被测试的模块
      Top dut (
        .clk(clk),
        .reset(reset),
        .hsync(hsync),
        .vsync(vsync),
        .red(red),
        .green(green),
        .blue(blue)
      );
    
      // 时钟生成
      always #5 clk = ~clk;
    
      // 复位信号生成
      initial begin
        reset = 1;
        #10;
        reset = 0;
        #10000;
        $finish;
      end
    
      // 输出测试结果
      always @(posedge clk) begin
        $display("hsync: %b, vsync: %b, red: %h, green: %h, blue: %h", hsync, vsync, red, green, blue);
      end
    
    endmodule
    

    效果

    在这里插入图片描述

    流水灯程序设计

    流水灯模块

    module LED(
        input clk,
        input rst_n,  // _n低电平有效
        output logic [3:0] led
    );
    
    // 1.5s计数器
    logic [27:0] cnt;
    parameter int TIME_1_5S = 75_000_000;
    // 由于cnt已经声明为logic类型,不需要额外的信号声明
     logic add_cnt;
     logic end_cnt;
    
    // 赋值语句不需要阻塞赋值的begin-end结构
    always_ff @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            cnt <= 28'd0;
        end else if (add_cnt) begin
            if (end_cnt) begin
                cnt <= 28'd0;
            end else begin
                cnt <= cnt + 1;
            end
        end
    end
    
    // 使用always_comb声明组合逻辑
    always_comb begin
        add_cnt = 1'b1;
        end_cnt = add_cnt && cnt == (TIME_1_5S - 1);
    end
    
    // 拼接法控制LED
    always_ff @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            led <= 4'b1110;
        end else if (end_cnt) begin
            led <= {led[2:0], led[3]}; // 流水灯
        end
    end
    
    endmodule
    

    顶层模块设计

    `timescale 1ns/1ns
    module     LED_tb();
    
    reg   tb_clk;
    reg   tb_rst_n;
    wire  [3:0]tb_led;
    
    
    LED #(.TIME_1_5S(750))           inst_LED(
       .clk      (tb_clk     ) ,
       .rst_n    (tb_rst_n   ) ,
       .led      (tb_led )   
    );
                parameter cycle =20 ;//时钟周期为20ns
                always#(cycle/2)tb_clk=~tb_clk;//过时钟周期一半取反
    
            initial begin
                tb_clk=1'b0;
                tb_rst_n=1'b0;
                #(cycle*3);
                tb_rst_n=1'b1;
                #(cycle*751*16);
                $stop;
            end
    
    endmodule
    

    效果

    在这里插入图片描述

    在这里插入图片描述

    总结

    这次对system verilog的编写让我对system verilog有了清晰的认识。

  • 相关阅读:
    论文阅读笔记(十一)——BioInformatics Agent (BIA)
    springboot实现WebAPI版本控制
    达梦数据库基础操作(一):用户操作
    一文了解 history 和 react-router 的实现原理
    万古霉素修饰银纳米粒/磁性纳米微球/负载万古霉素PLGA缓释微球/硅包银纳米三角片
    华为云云耀云服务器L实例评测 | 基于docker部署nacos2.2.3服务
    独立产品灵感周刊 DecoHack #040 - Google公布2022年度最佳应用榜单
    Huggingface——tensorboard监控训练过程
    【人月神话】深入了解软件工程和项目管理
    如何在启用Secure Boot的Ubuntu 22.04电脑中安装使用VirtualBox 6.1
  • 原文地址:https://blog.csdn.net/qq_71979946/article/details/139425593