我希望通过 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 中可能非常棘手。
要记住的两个主要规则是:
- 一定要为符号位分配一个额外的位。虽然你可以
在 10b 无符号中表示 0..1023。那变成 -512..511 当
签名。
- 在 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
注意几点:
- localparams中的's'表示有符号常量
- $signed 系统任务强制将值视为已签名。请注意我是如何添加前导零的,这样如果设置了输入信号的高位,我们就不会无意中得到负数。
所以基本上我希望我的显示器显示一条负斜率线。我编写的当前代码完美地显示了任何正斜率线,但是如果我试图将其设为负值,则它不会出现或变成虚线。 我对为什么它不起作用有一个模糊的想法,但是如果有人能指出我正确的方向,我将不胜感激。
(注意:我的 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 中可能非常棘手。
要记住的两个主要规则是:
- 一定要为符号位分配一个额外的位。虽然你可以 在 10b 无符号中表示 0..1023。那变成 -512..511 当 签名。
- 在 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
注意几点:
- localparams中的's'表示有符号常量
- $signed 系统任务强制将值视为已签名。请注意我是如何添加前导零的,这样如果设置了输入信号的高位,我们就不会无意中得到负数。