vhdl - 有没有更好的使用for循环的方法?
问题描述
我正在编写(128 位)(4 位)幂的代码和一个除法器,以找到(128 位)(4 位)幂的余数和(4 位)的变量。我使用重复加法来找到第一个操作,并使用重复减法来找到余数。我用for循环来做同样的事情。对于(4 位)的(128 位)幂,for 循环的上限非常高,并且模拟给出了错误。模拟突然停止,说进程已终止。并且在模块电源中发现了一个致命错误(Windows xp 上的 Xilinx 12.1)。此错误在 windows 10 上的 xilinx 14.7 上弹出:
ERROR:Portability:3 - 此 Xilinx 应用程序内存不足或遇到内存冲突。当前内存使用量为 3085052 kb。您可以尝试增加系统的物理或虚拟内存。如果您使用的是 Win32 系统,则可以使用 boot.ini 文件中的 /3G 开关将应用程序内存从 2GB 增加到 3GB。有关这方面的更多信息,请参阅 Xilinx 答复记录 #14932。有关此问题的技术支持,请访问http://www.xilinx.com/support。
模拟器以意外方式终止。有关详细信息,请查看 ISim 日志 (isim.log)。有没有什么有效的方法可以避免这个问题?请帮忙。寻找力量:
entity power is
Port ( mes : in STD_LOGIC_VECTOR (207 downto 0);
d : in STD_LOGIC_VECTOR (11 downto 0);
outt : out STD_LOGIC_VECTOR (2007 downto 0);
clk : in STD_LOGIC);
end power;
architecture Behavioral of power is
signal mes1:unsigned (207 downto 0);
signal d1:unsigned (11 downto 0);
signal mes3:unsigned (2007 downto 0);
begin
process(clk)
begin
if(clk'event and clk='1') then
mes1<=unsigned(mes);
d1<=unsigned(d);
end if;
end process;
process(clk,mes1)
variable varr:unsigned (2007 downto 0);
variable cnt,cnt1: unsigned (207 downto 0);
variable mes2: unsigned (2007 downto 0);
begin
cnt:=x"0000000000000000000000000000000000000000000000000001";
mes2:=x"0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
mes2(207 downto 0):=mes1;
if(clk'event and clk='1') then
for i in 0 to 90 loop
if(cnt<d1) then
varr:=x"0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
cnt1:=x"0000000000000000000000000000000000000000000000000001";
for j in 0 to 150000 loop
if (cnt1<=mes1) then
varr:=varr+mes2;
cnt1:=cnt1+1;
end if;
end loop;
mes2:=varr;
cnt:=cnt+1;
end if;
end loop;
mes3<=mes2;
end if;
end process;
process(clk)
begin
if(clk'event and clk='1') then
outt<=std_logic_vector(mes3);
end if;
end process;
end Behavioral;
要找到余数:
entity div22 is
Port ( a : in STD_LOGIC_VECTOR (2007 downto 0);
b : in STD_LOGIC_VECTOR (7 downto 0);
remi : out STD_LOGIC_VECTOR (2007 downto 0);
clk : in STD_LOGIC);
end div22;
architecture Behavioral of div22 is
signal q:unsigned (11 downto 0);
signal a1,r:unsigned (2007 downto 0);
signal b1:unsigned (7 downto 0);
--signal i:STD_LOGIC_VECTOR (3 downto 0);
begin
process(clk)
begin
if(clk'event and clk='1') then
a1<=unsigned(a);
b1<=unsigned(b);
end if;
end process;
process(clk,a1,b1)
variable remo1,remo2: unsigned(2007 downto 0);
begin
remo1:=a1;
if RISING_EDGE(clk) then
for i in 0 to 150000 loop
remo2:=remo1;
if(remo2>=b1) then
remo1:=remo2-b1;
end if;
end loop;
r<=remo1;
end if;
end process;
process(clk,r)
begin
if RISING_EDGE(clk) then
remi<= std_logic_vector(r);
end if;
end process;
end Behavioral;
要找到提醒,for 循环的上限非常高。有没有什么有效的方法来解决这个问题?请帮忙。
解决方案
在您的上下文中,最好的方法是不使用循环。
通常,为了获得最佳性能和可接受的实现区域大小,您应该使用状态实现 (fsm)。您应该在频率(关键路径)和完成工作所需的周期数之间取得平衡。这是我的硕士论文中“总除法的其余部分 - 余数”操作的基本实现(在 Verilog 中)。就我而言,问题是加法器太大了。所以在我的最终版本中,添加实现是并行的——我使用了一些较小的加法器来获得更好的频率。此代码是我的硕士论文的 RSA 实现的一部分。
module div(a,n,clk,reset,R, ready); // a,b,n mniejszy rozmiar
// a mod n = R
parameter size=1024; // data length
parameter
A0 = 2'b00, // Reset.
A1 = 2'b01, // Find _n > _R.
A2 = 2'b10, // Calc.
A3 = 2'b11; // Ready - calc done.
input [size-1:0] a,n;
input clk,reset;
output ready;
output [size-1:0] R;
reg signed [size:0] _R;
reg [size:0] _n;
reg [size-1:0] tmp_r;
reg ready; // operation is done.
reg [11:0]i;
(*safe_implementation = "yes"*)// directive for XST
(* signal_encoding = "user" *) // directive for XST
(* fsm_encoding = "user" *) // directive for XST
reg [1:0] cs;
initial
begin
_R = 0;
_n = 0;
i = 0;
ready = 0;
tmp_r = 0;
cs = A0;
end
always @(posedge clk)
begin
if (reset)
begin
_R = a;
_n = n;
i = 0;
tmp_r= a;
ready = 0;
cs = A0;
end
else
begin
case(cs)
A0:
begin
cs = A1;
end
A1:
begin
_n = _n << 1;
i = i + 1;
if ( _n > _R )
begin
_n = _n >> 1;
_R = _R - _n;
cs = A2;
end
else
begin
cs = A1;
end
end
A2:
begin
if (i==0)
begin
cs = A3;
end
else
begin
_n = _n >> 1;
if (_R[size]==1'b0)
begin
tmp_r = _R; // Save last positiv number.
_R = _R - _n;
end
else
begin
_R = _R + _n;
end
i = i -1;
cs = A2;
end
end
A3:
begin
ready = 1'b1;
cs = A3;
end
default:;
endcase
end
end
assign R=tmp_r;
endmodule
您可以在我的硕士论文中找到更多技巧来获得适用于您的上下文的更好性能和区域优化(问题是它是波兰语): https ://www.researchgate.net/publication/332752272_Realizacja_wybranych_algorytmow_kryptograficznych_w_strukturach_FPGA_Smolinski_Lukasz
对不起我的英语不好。
推荐阅读
- doxygen - 删除 RTF doxygen 输出中的索引
- java - 使用 Hibernate/Oracle 将所有内容拉入内存的 ScrollableResults
- javascript - 仅当变量查询运算符不为空时才使用它们
- ruby-on-rails - 努力获取 CSV 报告以在请求时加载
- authentication - 使用 JWT 时如何返回特定的状态码
- c# - 由于配置的标识不正确,无法启动服务器进程。检查用户名和密码
- javascript - Javascript href 导航到不属于我的其他 url 然后自动滚动到一个类
- python - 让所有边连接到 NetworkX 中多向图中的一组节点的最快方法?
- regex - 如何使用.htaccess将带有查询字符串的url重定向到带有查询字符串的另一个url
- terraform - 使用 terraform-cloudflare 提供程序的 Cloudflare 页面规则不会更新页面规则