我正在使用行为建模方法设计Verilog中的加密模块,但我被困在将寄存器值传递到Data_out端口。我在Data_out端口复制寄存器p值时犯了一点错误。试验台也附有。模块的预期输出应该是Data_out = (Data_in + Key) MOD 26。但是由于合成问题,我们不能使用%操作符。你的回答对我很有价值。
module encription(Start,Clk,Reset,Data_In, Key,Data_out,Done);
parameter M='d26;
parameter S0=0, S1=1, S2= 2;
input Clk,Reset,Start;
input [4:0] Data_In,Key;
output reg [4:0] Data_out;
output reg Done;
reg [1:0] state;
reg [4:0] p,q,r,s;
always @ (posedge Clk)
begin
r <= Data_In;
s <= Key;
end
always @ (posedge Clk )
begin
if(Reset=='b0)
begin
Done <= 1'b0;
p <= M;
end
else if (Reset == 'b1)
case (state)
S0:
if (Start) begin
q <= r + s;
state <= S1;
end
S1:
if (p >= q) begin
p <= p - q;
state <= S2;
end
S2:
begin
Data_out <= p;
Done <= 1'b1;
Done <= 1'b0;
end
default:
state <= S0;
endcase
end
endmodule
module Encryption_tb();
reg Clk,Reset,Start;
reg [4:0] Data_In,Key;
wire [4:0] Data_out;
wire [4:0] q;
wire Done;
encription DUT(Start,Clk,Reset,Data_In, Key,Data_out,Done);
initial
begin
Clk = 0;
forever #5 Clk=~Clk;
end
initial
begin
#10 Start = 'b1; Data_In = 'b000111; Key = 'b01110;
#10 Start = 'b1; Data_In = 'b000101; Key = 'b01100;
#10 Start = 'b1; Data_In = 'b000001; Key = 'b00110;
#10 Reset = 'b1; Start = 'b1;
//#10 Reset = 'b0;
#10 Start = 'b1; Data_In = 'b000111; Key = 'b01110;
#10 Start = 'b1; Data_In = 'b000101; Key = 'b01100;
#10 Start = 'b1; Data_In = 'b000001; Key = 'b00110;
#10 $finish;
end
endmodule
这并不需要状态机,只需要一些flops。
RTL:
module encription(Start,Clk,Reset,Data_In, Key,Data_out,Done);
parameter M='d26;
parameter S0=0, S1=1, S2= 2;
input Clk,Reset,Start;
input [4:0] Data_In,Key;
output reg [4:0] Data_out;
output reg Done;
reg [6:0] sum;
assign sum = Data_In + Key;
always @ (posedge Clk )
begin
if(Reset=='b1)
begin
Data_out <= 0;
Done <= 0;
end
else
begin
if(sum < M)
Data_out <= sum;
else
if(sum < 2*M)
Data_out <= sum - M;
else
Data_out <= sum - 2*M ;
Done <= Start;
end
end
endmodule
有意义向量测试平台:
module Encryption_tb();
reg Clk,Reset,Start;
reg [4:0] Data_In,Key;
wire [4:0] Data_out;
wire [4:0] q;
wire Done;
encription DUT(Start,Clk,Reset,Data_In, Key,Data_out,Done);
initial
begin
Clk = 0;
forever #5 Clk=~Clk;
end
initial
begin :initial_block
$monitor("Data_In = %d,Key = %d, Data_out = %d",Data_In,Key,Data_out);
Reset = 1;
#20 Reset = 0;
#10;
#1;
Start = 1;
for(int i = 0; i < 30; i++)
begin
@ (posedge Clk);
#1;
Key = i;
Data_In = i;
end
#10 $finish;
end :initial_block
initial
begin
$dumpfile("dump.vcd");
$dumpvars;
end
endmodule
一些输出(注意,由于flops,答案延迟了1个clk)
Data_In = 0,Key = 0, Data_out = 0
Data_In = 1,Key = 1, Data_out = 0
Data_In = 1,Key = 1, Data_out = 2
Data_In = 2,Key = 2, Data_out = 2
Data_In = 2,Key = 2, Data_out = 4
Data_In = 3,Key = 3, Data_out = 4
Data_In = 3,Key = 3, Data_out = 6
Data_In = 4,Key = 4, Data_out = 6
Data_In = 4,Key = 4, Data_out = 8
Data_In = 5,Key = 5, Data_out = 8
Data_In = 5,Key = 5, Data_out = 10
Data_In = 6,Key = 6, Data_out = 10
Data_In = 6,Key = 6, Data_out = 12
Data_In = 7,Key = 7, Data_out = 12
Data_In = 7,Key = 7, Data_out = 14
Data_In = 8,Key = 8, Data_out = 14
Data_In = 8,Key = 8, Data_out = 16
Data_In = 9,Key = 9, Data_out = 16
Data_In = 9,Key = 9, Data_out = 18
Data_In = 10,Key = 10, Data_out = 18
Data_In = 10,Key = 10, Data_out = 20
Data_In = 11,Key = 11, Data_out = 20
Data_In = 11,Key = 11, Data_out = 22
Data_In = 12,Key = 12, Data_out = 22
Data_In = 12,Key = 12, Data_out = 24
Data_In = 13,Key = 13, Data_out = 24
Data_In = 13,Key = 13, Data_out = 0
Data_In = 14,Key = 14, Data_out = 0
Data_In = 14,Key = 14, Data_out = 2
Data_In = 15,Key = 15, Data_out = 2
Data_In = 15,Key = 15, Data_out = 4
Data_In = 16,Key = 16, Data_out = 4
Data_In = 16,Key = 16, Data_out = 6
Data_In = 17,Key = 17, Data_out = 6
Data_In = 17,Key = 17, Data_out = 8
Data_In = 18,Key = 18, Data_out = 8
我看到了几个问题。
-
在状态机中摆脱S1的唯一方法是if "if (p>= q)"。如果p已经小于Q,你将永远停留在那个状态
-
在您的测试台中,您为您的状态在启动之间分配时间机器运行
几点建议:更好的缩进可以更容易地看到代码块内部的内容:Ex:
S1:
if (p >= q) begin
p <= p - q;
state <= S2;
end
在你的测试台中,而不是使用#10来定义刺激序列,使用@(posedge Clk),这样,如果你的时钟频率改变或在TB中使用一些其他长度的延迟,事情仍然会与时钟对齐。使用@(Done)来等待结果。
我也很好奇,你用的什么合成工具不支持%?