首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >640x480@60 VGA同步发生器

640x480@60 VGA同步发生器
EN

Code Review用户
提问于 2019-07-12 03:14:30
回答 1查看 581关注 0票数 6

我用Verilog写了我的第一个模块。其目的是维护两个计数器并发出与VGA的HSync和VSync相对应的信号,以及视频控制器用于消隐间隔的HBlank和VBlank脉冲。唯一的输入是25.175 MHz的时钟信号。所有的时间信息都是从这里获取的。

代码语言:javascript
复制
module sync (clk, hblank, hsync, vblank, vsync) ;
  input clk;
  output reg hblank = 0, hsync = 1, vblank = 0, vsync = 1;
  reg [9:0] hcnt = 0, vcnt = 0;

  always @(posedge clk) begin
    case (hcnt)
      640: hblank <= 1;
      656: hsync <= 0;
      752: hsync <= 1;
      800: begin
        hblank <= 0;
        hcnt <= 0;
        vcnt <= vcnt + 1;
      end
    endcase
    case (vcnt)
      480: vblank <= 1;
      490: vsync <= 0;
      492: vsync <= 1;
      525: begin
        vblank <= 0;
        vcnt <= 0;
      end
    endcase
    hcnt <= hcnt + 1;
  end
endmodule
EN

回答 1

Code Review用户

发布于 2019-07-24 00:19:55

如果您已经运行仿真或加载到FPGA,您会注意到您没有得到预期的行为。在加载到FPGA之前,运行仿真并查看波形。

在始终块的底部有hcnt <= hcnt + 1;,这将覆盖hcnt <= 0;,这不是您想要的。<=是一个非阻塞的赋值,这意味着它将被立即评估,但值将在时间步骤结束之前不会被更新。秩序很重要。

最简单的解决方案是将hcnt <= hcnt + 1;移到case语句之上。

请注意,您的hcnt正在计数从0到800,即801时钟。您可能需要考虑从每种情况中减去1,或者启动/重置hcnt (和vcnt)为1,而不是0。

您的vcnt将仅为525一个时钟,这看起来不是故意的。考虑将其移动到case(hcnt)的S条件800内。

我将建议添加一个重置输入。并建议使用ANSI头,非ANSI是必需的Verilog-95和前IEEE1364.自Verilog-2001以来,ANSI风格是首选的,主要是因为它减少了输入量。

以下是我的建议。注意,我还没有测试是否满足了所有的功能需求(这应该在您的testbench中完成)。

代码语言:javascript
复制
module sync (
  input clk, rst_n,                       // <-- ANSI header
  output reg hblank, hsync, vblank, vsync
);
  reg [9:0] hcnt, vcnt;

  always @(posedge clk) begin
    if (!rst_n) begin // <-- synchronous reset logic
      hblank <= 1'b0;
      hsync <= 1'b1;
      vblank <= 1'b0;
      vsync <= 1'b1;
      hcnt <= 10'h001;  // <-- init as 1 so case index doesn't need to change
      vcnt <= 10'h001;  // <-- same as vcnt
    end
    else begin
      hcnt <= hcnt + 10'h001; // <-- default assignment, will be updated after the clock
      case (hcnt) // <-- uses the sampled value, not the result of the above line
        10'd640: hblank <= 1'b1;
        10'd656: hsync <= 1'b0;
        10'd752: hsync <= 1'b1;
        10'd800: begin
          hblank <= 1'b0;
          hcnt <= 10'h001; // <-- reset as 1, last assignment wins
          vcnt <= vcnt + 10'h001;
          case (vcnt)
            10'd480: vblank <= 1'b1;
            10'd490: vsync <= 1'b0;
            10'd492: vsync <= 1'b1;
            10'd525: begin
              vblank <= 1'b0;
              vcnt <= 10'h001; // <-- reset as 1, last assignment wins
            end
          endcase
        end
      endcase
    end
  end
endmodule

您可能需要考虑使用2路块编码风格。它确实需要更多的代码行--小设计(通常减少大型/复杂设计的代码行数)。主要的好处是您可以访问当前状态和失败的下一个状态。

代码语言:javascript
复制
// sequential logic (uses non-blocking assignment and is synchronous)
always @(posedge clk) begin
  if (!rst_n) begin
    hblank <= 1'b0;
    hsync <= 1'b1;
    vblank <= 1'b0;
    vsync <= 1'b1;
    hcnt <= 10'h001;
    vcnt <= 10'h001;
  end
  else begin
    hblank <= next_hblank;
    hsync <= next_hsync;
    vblank <= next_vblank;
    vsync <= next_vsync;
    hcnt <= next_hcnt;
    vcnt <= next_vcnt;
  end
end

// combinational logic (uses blocking assignment and is asynchronous)
always @* begin
  next_hblank = hblank; // <-- default keep previous
  next_hsync = hsync;
  next_vblank = vblank;
  next_vsync = vsync;
  next_hcnt = hcnt + 10'h001; // <-- default increment
  next_vcnt = vcnt;

  // calc next values, update as needed
  case (hcnt)
    10'd640: next_hblank = 1'b1;
    10'd656: next_hsync = 1'b0;
    10'd752: next_hsync = 1'b1;
    10'd800: begin
      next_hblank = 1'b0;
      next_hcnt = 10'h001;
      next_vcnt = vcnt + 10'h001;
      case (vcnt)
        10'd480: next_vblank = 1'b1;
        10'd490: next_vsync = 1'b0;
        10'd492: next_vsync = 1'b1;
        10'd525: begin
          next_vblank = 1'b0;
          next_vcnt = 10'h001;
        end
      endcase
    end
  endcase
end
票数 1
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/223996

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档