在Verilog行为建模中复制寄存器值



我正在使用行为建模方法设计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

我看到了几个问题。

  1. 在状态机中摆脱S1的唯一方法是if "if (p>= q)"。如果p已经小于Q,你将永远停留在那个状态

  2. 在您的测试台中,您为您的状态在启动之间分配时间机器运行

几点建议:更好的缩进可以更容易地看到代码块内部的内容:Ex:

S1: 
if (p >= q) begin
p <= p - q;
state <= S2;
end

在你的测试台中,而不是使用#10来定义刺激序列,使用@(posedge Clk),这样,如果你的时钟频率改变或在TB中使用一些其他长度的延迟,事情仍然会与时钟对齐。使用@(Done)来等待结果。

我也很好奇,你用的什么合成工具不支持%?

最新更新