如何在verilog中填写FPGA生成的圆圈,以进行合成和VGA输出?

如何在verilog中填写FPGA生成的圆圈,以进行合成和VGA输出?,verilog,synthesis,vga,Verilog,Synthesis,Vga,我想在640x480 VGA显示器上输出一个半径为100像素的移动红色圆圈。我被困在如何制作和填充实际的圆圈上。 现在,我看了一下令人麻木的Bresenham算法,但我无法使它们适合我的verilog代码 我已经从理论上解释了我能做什么,但我不完全确定这是可能的。 我知道圆的方程是(x-a)(x-a)+(y-b)(y-b)=r*r,其中(a,b)是原点。 所以我想用RGB颜色填充这个圆圈,并将它从上到下移动,即在a=640/2时从b=0移动到480 由于VGA从左到右输出像素,向下迭代,我猜我必

我想在640x480 VGA显示器上输出一个半径为100像素的移动红色圆圈。我被困在如何制作和填充实际的圆圈上。 现在,我看了一下令人麻木的Bresenham算法,但我无法使它们适合我的verilog代码

我已经从理论上解释了我能做什么,但我不完全确定这是可能的。 我知道圆的方程是(x-a)(x-a)+(y-b)(y-b)=r*r,其中(a,b)是原点。 所以我想用RGB颜色填充这个圆圈,并将它从上到下移动,即在a=640/2时从b=0移动到480

由于VGA从左到右输出像素,向下迭代,我猜我必须使用嵌套循环。 我知道垂直运动的第一个循环是从0到480。 这是我遇到问题的第二个循环。它从0到640,但我希望像素在到达(x,y)(沿圆的一个点)时改变颜色,保留该颜色,然后在经过(x+k)(其中k是水平弦)后改变回去

基本上,如果下面是我圆圈的水平弦:

_黑色(x,y)红色(k像素)(x+k,y)黑色

reg[8:0]bally//圆心的y坐标
reg[8:0]rad//半径
始终@(posedge clk)
开始

for(VCount=0;VCount我不确定嵌套for循环的行为是否会像您认为的那样,至少对于合成设计是这样

我的建议是,不要根据圆的参数方程生成圆,这是我认为您想要做的。相反,如果圆总是相同的(即,它的半径总是小于等于100像素),则预生成圆的位图并将其存储在FPGA(块RAM)中内存作为一个大精灵。它不会占用您太多空间。精灵中的0位将转换为“透明”,而1位将意味着使用与精灵(圆)关联的颜色绘制此点

这样,绘制屏幕(实际上是屏幕的活动部分)的代码如下所示:

`define SPRLEN 256  // how many pixels in width and heigh the sprite will have.
`define SPRITECOLOR 3'b100;  // RED ball. (RGB, 1-bit per channel)
`define BGCOLOR 3'010;       // GREEN background

reg ballsprite[0:`SPRLEN*`SPRLEN-1]; // A matrix to hold your sprite.
reg [9:0] hcont, vcont; // horizontal and vertical counters for scanning a VGA picture
reg [8:0] ballx, bally; //coordinates of the left-top corner of the ball sprite
reg [7:0] coorx,coory;  //X,Y coordinates of the current sprite position to draw

initial begin  // read your sprite definition into memory. FPGA synthetizable.
  $readmemb ("mysprite.bin", ballsprite);
end

// process to obtain relative coordinates of the current screen position within the sprite 
always @* begin
  coorx = hcont+1-ballx;
  coory = vcont+1-bally;
end

// process to get the next dot from the sprite. We begin at ballx-1,bally-1 because
// there's one clock delay in getting the current sprite dot value.
always @(posedge clk) begin
  if (hcont>=ballx-1 && hcont<=ballx-1+`SPRLEN && vcont>=bally-1 && vcont<=bally-1+`SPRLEN)
    dot_from_ball <= ballsprite[{coory,coorx}];  // i.e. coory*256+coorx
  else
    dot_from_ball <= 1'b0;  // if scan trace is not under the boundaries of the sprite,
                            // then it's transparent color
end

// multiplexer to actually put an RGB value on screen
always @* begin
  if (hcont>=0 && hcont<640 && vcont>=0 && vcont<480) begin
    if (dot_from_ball)
      {R,G,B} = `SPRITECOLOR;
    else
      {R,G,B} = `BGCOLOR;
  end
  else
    {R,G,B} = 3'b000;  //if not into active area, mute RGB
end
`define SPRLEN 256//精灵的宽度和高度有多少像素。
`定义SPRITECOLOR 3'b100;//红色球。(RGB,每个通道1位)
`定义BGCOLOR 3'010;//绿色背景
reg ballsprite[0:`SPRLEN*`SPRLEN-1];//存放精灵的矩阵。
reg[9:0]hcont,vcont;//用于扫描VGA图片的水平和垂直计数器
reg[8:0]ballx,bally;//球精灵左上角的坐标
reg[7:0]coorx,coory;//要绘制的当前精灵位置的X,Y坐标
初始开始//将精灵定义读入内存。FPGA可合成。
$readmemb(“mysprite.bin”,ballsprite);
终止
//获取精灵中当前屏幕位置的相对坐标的过程
总是开始
coorx=hcont+1-ballx;
coory=vcont+1-bally;
终止
//我们从ballx-1,bally-1开始,因为
//获取当前精灵点值时有一个时钟延迟。
始终@(posedge clk)开始

如果(hcont>=ballx-1&&hcont=bally-1&&vcont,我不确定嵌套for循环的行为是否会像您认为的那样,至少对于合成设计是这样

我的建议是,不要根据圆的参数方程生成圆,这是我认为您想要做的。相反,如果圆总是相同的(即,它的半径总是小于等于100像素),则预生成圆的位图并将其存储在FPGA(块RAM)中内存作为一个大精灵。它不会占用您太多空间。精灵中的0位将转换为“透明”,而1位将意味着使用与精灵(圆)关联的颜色绘制此点

这样,绘制屏幕(实际上是屏幕的活动部分)的代码如下所示:

`define SPRLEN 256  // how many pixels in width and heigh the sprite will have.
`define SPRITECOLOR 3'b100;  // RED ball. (RGB, 1-bit per channel)
`define BGCOLOR 3'010;       // GREEN background

reg ballsprite[0:`SPRLEN*`SPRLEN-1]; // A matrix to hold your sprite.
reg [9:0] hcont, vcont; // horizontal and vertical counters for scanning a VGA picture
reg [8:0] ballx, bally; //coordinates of the left-top corner of the ball sprite
reg [7:0] coorx,coory;  //X,Y coordinates of the current sprite position to draw

initial begin  // read your sprite definition into memory. FPGA synthetizable.
  $readmemb ("mysprite.bin", ballsprite);
end

// process to obtain relative coordinates of the current screen position within the sprite 
always @* begin
  coorx = hcont+1-ballx;
  coory = vcont+1-bally;
end

// process to get the next dot from the sprite. We begin at ballx-1,bally-1 because
// there's one clock delay in getting the current sprite dot value.
always @(posedge clk) begin
  if (hcont>=ballx-1 && hcont<=ballx-1+`SPRLEN && vcont>=bally-1 && vcont<=bally-1+`SPRLEN)
    dot_from_ball <= ballsprite[{coory,coorx}];  // i.e. coory*256+coorx
  else
    dot_from_ball <= 1'b0;  // if scan trace is not under the boundaries of the sprite,
                            // then it's transparent color
end

// multiplexer to actually put an RGB value on screen
always @* begin
  if (hcont>=0 && hcont<640 && vcont>=0 && vcont<480) begin
    if (dot_from_ball)
      {R,G,B} = `SPRITECOLOR;
    else
      {R,G,B} = `BGCOLOR;
  end
  else
    {R,G,B} = 3'b000;  //if not into active area, mute RGB
end
`define SPRLEN 256//精灵的宽度和高度有多少像素。
`定义SPRITECOLOR 3'b100;//红色球。(RGB,每个通道1位)
`定义BGCOLOR 3'010;//绿色背景
reg ballsprite[0:`SPRLEN*`SPRLEN-1];//存放精灵的矩阵。
reg[9:0]hcont,vcont;//用于扫描VGA图片的水平和垂直计数器
reg[8:0]ballx,bally;//球精灵左上角的坐标
reg[7:0]coorx,coory;//要绘制的当前精灵位置的X,Y坐标
初始开始//将精灵定义读入内存。FPGA可合成。
$readmemb(“mysprite.bin”,ballsprite);
终止
//获取精灵中当前屏幕位置的相对坐标的过程
总是开始
coorx=hcont+1-ballx;
coory=vcont+1-bally;
终止
//我们从ballx-1,bally-1开始,因为
//获取当前精灵点值时有一个时钟延迟。
始终@(posedge clk)开始

如果(hcont>=ballx-1&&hcont=bally-1&&vcont您不希望出现这样的循环。如果您希望动态生成一个圆(而不是使用位图),请在单独的过程中跟踪当前坐标(
始终
块)。每个始终块将在VGA时钟的每个滴答声上运行,因此每次执行该块时,您都有一个新的像素位置

然后使用另一个
始终
块,该块查看x和y坐标,并确定当前点是否在圆中。根据该决定,您可以选择前景或背景颜色。同样,这对每个像素按顺序操作一次

棘手的部分是决定当前点是否在圆中

如果这看起来有点太难开始,画一个正方形,因为它的方程非常简单。一旦你了解了它的工作原理,你就可以开始画圆(和其他参数定义的形状)。要在扫描图像时找到动态渲染这些形状的方法,可以使用术语“扫描线”
x^2 + y^2 = r^2
x^2 + y^2 < r^2
(x-xc)^2 + (y-yc)^2 < r^2