我正在尝试编写一个verilog代码来实现640X480像素图像的人口普查变换。我以行为形式编写了完整的代码。但代码合成时间太长。我明白原因可能是长寄存器数组和循环,但我不知道如何处理它 这是我的代码:
module test(in,clk,out
);
input clk;
input [7:0] in;
output [119:0]out;
reg [7:0]matrix[0:639][0:479];
//reg [119:0]win[0:10][0:10];
reg [9:0] i = 0;
reg [8:0] j = 0;
reg [12:0] count = 0;
integer p,q = 6;
integer a,b = -6;
reg [119:0]censusTransformedImage;
reg [119:0]census=0;
always@ (posedge clk)
begin
if(count<=6411)
count = count+1;
end
always @ (posedge clk )
begin
if(i<=639)
begin
matrix[i][j]=in;
i=i+1;
end
else if(i==639 && j<=479)
begin
i=0;
j=j+1;
end
//end
end
always @ (posedge clk)
begin
if(count > 6411)
begin
if(p<=634)
begin
if(q<=479)
begin
//census = 0;
if(a<=6)
begin
if(b<=6)
begin
if(~(a==0 && b==0))
census=census<<1;
if (matrix[p+a][q+b] > matrix[p][q])
census=census+1;
b = b+1;
end
else
begin
b=-6;
a=a+1;
end
end
else
begin
censusTransformedImage=census;
census=0;
a=-6;
q=q+1;
end
end
else
begin
q=0;
p=p+1;
end
end
end
end
assign out = censusTransformedImage;
endmodule
答案 0 :(得分:0)
合成器可能会尝试将矩阵实现为分布式内存。也就是说,使用取自FPGA片的触发器。必须避免这种情况,因为您只需耗尽FPGA器件的所有资源来实现该存储器。
相反,将矩阵存储器设计为独立模块,具有一个输入地址(坐标i,j),一个8位输出数据和一个8位输入数据。类似的东西:
module matrix (
input clk,
input wire [9:0] i,
input wire [8:0] j,
input write_enable,
input wire [7:0] din,
output reg [7:0] dout
);
reg [7:0] M[0:307199]; // your 640x480 matrix
wire [18:0] addr;
assign addr = i*640+j; // let's hope the synthesizer is able to
// implement this without having to use
// an actual multiplication engine
// (it shouldn't need to)
always @(posedge clk) begin
if (write_enable == 1'b1)
M[addr] <= din;
dout <= M[addr];
end
endmodule
这里的关键点是在每个时钟周期只有一个访问矩阵寄存器(M),并且输入和输出数据都被注册。通过这种方式,合成器将能够利用Block RAM而不是分布式RAM实现这个巨大的寄存器,利用大量切片,加速合成过程。
当然,这也意味着您的控制器必须以这样的方式编写:对于每个时钟周期,只能对您的矩阵执行一次操作,无论是读取还是写入。例如,您不允许在同一时钟周期中读取两个不同的元素。如果在同一时钟周期中需要两个不同的元素(正如您当前的代码所示),请重写此模块,以便提供两组输入坐标以及两个输出数据端口。希望合成器能为它推断出双端口存储器块。
作为测试,指示合成器仅合成矩阵模块并观察有关使用Block RAM实现的M的综合消息,吸收此寄存器等,以确保它不会使用分布式实现RAM再次。