我想在always块中使用另一个模块的输出。 目前使此代码工作的唯一方法是在 pi_in 分配后添加#1 ,以便有足够的时间让Pi完成。
模块pLayer.v的相关部分:
jQuery("#tableWithId").on("click", ".single_add_to_cart_button", function(e) {
e.preventDefault();
var url = jQuery(this).data('href');
window.open(url, '_blank');
return false;
});
Modllue Pi.v
Pi pi(pi_in,pi_out);
always @(*)
begin
for(i=0; i<constants.nSBox; i++) begin
for(j=0; j<8; j++) begin
x = (state_value[(constants.nSBox-1)-i]>>j) & 1'b1;
pi_in = 8*i+j;#1; /* wait for pi to finish */
PermutedBitNo = pi_out;
y = PermutedBitNo>>3;
tmp[(constants.nSBox-1)-y] ^= x<<(PermutedBitNo-8*y);
end
end
state_out = tmp;
end
在最终实施中不应使用延迟,那么有没有使用#1 的另一种方式?
本质上我希望只有在Pi模块以pi_in(= 8 * i + j)作为输入完成其作业后才能评估 PermutedBitNo = pi_out 。 我怎么能阻止这条线直到Pi完成?
我必须使用时钟吗?如果是这样的话,请给我一个提示。
更新
根据Krouitch的建议我修改了我的模块。这是更新版本:
来自pLayer.v:
`include "constants.v"
module Pi(in, out);
input [31:0] in;
output [31:0] out;
reg [31:0] out;
always @* begin
if (in != constants.nBits-1) begin
out = (in*constants.nBits/4)%(constants.nBits-1);
end else begin
out = constants.nBits-1;
end
end
endmodule
来自Pi.v:
Pi pi(.clk (clk),
.rst (rst),
.in (pi_in),
.out (pi_out));
counter c_i (clk, rst, stp_i, lmt_i, i);
counter c_j (clk, rst, stp_j, lmt_j, j);
always @(posedge clk)
begin
if (rst) begin
state_out = 0;
end else begin
if (c_j.count == lmt_j) begin
stp_i = 1;
end else begin
stp_i = 0;
end
// here, the logic starts
x = (state_value[(constants.nSBox-1)-i]>>j) & 1'b1;
pi_in = 8*i+j;
PermutedBitNo = pi_out;
y = PermutedBitNo>>3;
tmp[(constants.nSBox-1)-y] ^= x<<(PermutedBitNo-8*y);
// at end
if (i == lmt_i-1)
if (j == lmt_j) begin
state_out = tmp;
end
end
end
endmodule
module counter(
input wire clk,
input wire rst,
input wire stp,
input wire [32:0] lmt,
output reg [32:0] count
);
always@(posedge clk or posedge rst)
if(rst)
count <= 0;
else if (count >= lmt)
count <= 0;
else if (stp)
count <= count + 1;
endmodule
答案 0 :(得分:3)
这是你在这里的一个很好的软件......
这种语言描述硬件的事实并没有帮助。
在verilog中,你写的东西会在零时间内模拟。这意味着i
和j
上的循环也将在零时间内完成。这就是为什么当你强制循环使用#1
等待1个时间单位时你看到的东西。
是的,你必须使用时钟。
为了让您的系统正常工作,我必须实现i
和j
的计数器。
带复位的计数器同步计数器可以这样写:
`define SIZE 10
module counter(
input wire clk,
input wire rst_n,
output reg [`SIZE-1:0] count
);
always@(posedge clk or negedge rst_n)
if(~rst_n)
count <= `SIZE'd0;
else
count <= count + `SIZE'd1;
endmodule
您指定仅在处理pi_out
时才对pi_in
进行采样。
在数字设计中,这意味着您要在发送pi_in
的那一刻与您正在阅读pi_out
的那一刻之间等待一个时钟周期。
在我看来,最好的解决方案是让您的pi
模块顺序,然后将pi_out
视为注册。
要做到这一点,我会做以下事情:
module Pi(in, out);
input clk;
input [31:0] in;
output [31:0] out;
reg [31:0] out;
wire clk;
wire [31:0] out_comb;
always @* begin
if (in != constants.nBits-1) begin
out_comb = (in*constants.nBits/4)%(constants.nBits-1);
end else begin
out_comb = constants.nBits-1;
end
end
always@(posedge clk)
out <= out_comb;
endmodule
如果您使用i
和j
以及最后pi
模块的计数器,很快就会发生这种情况:
i
和j
会发生变化 - &gt; pi_in
会在同一时间(模拟中)相应更改out_comb
将存储在out
中,然后您将pi_out
的新值比pi_in
晚一个时钟周期修改强>
首先,在编写(同步)进程时,我建议您只按进程处理1个寄存器。它将使您的代码更清晰,更易于理解/调试。
另一个提示是将组合电路与顺序分开。它还可以使您的代码更清晰,更易理解。
如果我以前面写过的计数器为例,它看起来像是:
`define SIZE 10
module counter(
input wire clk,
input wire rst_n,
output reg [`SIZE-1:0] count
);
//Two way to do the combinatorial function
//First one
wire [`SIZE-1:0] count_next;
assign count_next = count + `SIZE'd1;
//Second one
reg [`SIZE-1:0] count_next;
always@*
count_next = count + `SIZE'1d1;
always@(posedge clk or negedge rst_n)
if(~rst_n)
count <= `SIZE'd0;
else
count <= count_next;
endmodule
在这里,我看到为什么你还有一个比预期更多的周期,这是因为你在同步过程中放置了控制pi
模块的组合电路。这意味着将发生以下情况:
clk
正边i
和j
pi_in
pi_out
被捕获所以它需要2个周期才有意义。
要纠正你应该从同步过程中取出'逻辑'部分。正如您在评论中所述,这是逻辑,所以它不应该在同步过程中。
希望有所帮助