我希望通过 VGA 在系统 verilog 中显示一条负斜率线(正确显示正斜率线)

I wish to display a line with a negative slope in system verilog through VGA (positive sloped lines are displayed correctly)

所以基本上我希望我的显示器显示一条负斜率线。我编写的当前代码完美地显示了任何正斜率线,但是如果我试图将其设为负值,则它不会出现或变成虚线。 我对为什么它不起作用有一个模糊的想法,但是如果有人能指出我正确的方向,我将不胜感激。

(注意:我的 VGA 驱动程序和 VGAWrapper 一样工作正常)

这是代码:

module vga_rgb(
    input logic [8:0] row_o, 
    input logic [9:0] column_o, 
    input logic clk_i,reset_i, 
    output logic [15:0]rgb_i
    );

  localparam X1 = 10'd200; 
  localparam Y1 = 9'd100;

  localparam X2 = 10'd400;
  localparam Y2 = 9'd300;

  wire [15:0] slope = ((Y2-Y1)/(X2-X1));

  always@(posedge clk_i, posedge reset_i)
    if (reset_i) 
      rgb_i <= 16'b0; 
    else 
      if (((row_o-Y1) == (slope * (column_o-X1))) && ((row_o < 300) && (row_o > 100/)))
        rgb_i <= 16'b0;
      else        
        rgb_i <= 16'b11111_111111_11111;

你快到了。负斜率的问题是,你现在正在处理带符号的数量,这在 Verilog 中可能非常棘手。

要记住的两个主要规则是:

  1. 一定要为符号位分配一个额外的位。虽然你可以 在 10b 无符号中表示 0..1023。那变成 -512..511 当 签名。
  2. 在 verilog 中,数学运算的结果是无符号的 除非 两个 操作数都已签名。这通常是深 对新手来说令人惊讶的行为,但这就是语言的工作方式。

因此,通过一些签名注释,固定常量的宽度,将输出减少到一位,并修复我认为是剪切和粘贴错误的内容,我最终得到了这个:

module vga_rgb(
    input wire [8:0] row_o,
    input wire [9:0] column_o,
    input logic clk_i,reset_i,
    output logic rgb_i
    );

  localparam X1 = 11'sd200;
  localparam Y1 = 10'sd100;

  localparam X2 = 11'sd400;
  localparam Y2 = 10'sd300;

  wire signed [15:0] slope = ((Y2-Y1)/(X2-X1));

  always@(posedge clk_i, posedge reset_i)
    if (reset_i)
      rgb_i <= 16'b0;
    else
      if ((($signed({1'b0, row_o})-Y1) == (slope * ($signed({1'b0, column_o})-X1))) && ((row_o < Y2) && (row_o > Y1)))
        rgb_i <= 1'b1;
      else
        rgb_i <= 1'b0;

endmodule

注意几点:

  1. localparams中的's'表示有符号常量
  2. $signed 系统任务强制将值视为已签名。请注意我是如何添加前导零的,这样如果设置了输入信号的高位,我们就不会无意中得到负数。