![](/img/trans.png)
[英]Verilog behavioral code getting simulated properly but not working as expected on FPGA
[英]My Verilog behavioral code getting simulated properly but not working as expected on FPGA
我使用狀態機概念為展位乘數(基數 2)編寫了一個行為程序。 我在使用modelsim的程序模擬過程中得到了正確的結果,但是當我將它移植到fpga(spartan 3)時,結果並不如預期。
我哪里錯了?
module booth_using_statemachine(Mul_A,Mul_B,Mul_Result,clk,reset);
input Mul_A,Mul_B,clk,reset;
output Mul_Result;
wire [7:0] Mul_A,Mul_B;
reg [7:0] Mul_Result;
reg [15:0] R_B;
reg [7:0] R_A;
reg prev;
reg [1:0] state;
reg [3:0] count;
parameter start=1 ,add=2 ,shift=3;
always @(state)
begin
case(state)
start:
begin
R_A <= Mul_A;
R_B <= {8'b00000000,Mul_B};
prev <= 1'b0;
count <= 3'b000;
Mul_Result <= R_B[7:0];
end
add:
begin
case({R_B[0],prev})
2'b00:
begin
prev <= 1'b0;
end
2'b01:
begin
R_B[15:8] <= R_B[15:8] + R_A;
prev <= 1'b0;
end
2'b10:
begin
R_B[15:8] <= R_B[15:8] - R_A;
prev <= 1'b1;
end
2'b11:
begin
prev <=1'b1;
end
endcase
end
shift:
begin
R_B <= {R_B[15],R_B[15:1]};
count <= count + 1;
end
endcase
end
always @(posedge clk or posedge reset)
begin
if(reset==1)
state <= start;
else
begin
case(state)
start:
state <= add;
add:
state <= shift;
shift:
begin
if(count>7)
state <= start;
else
state <=add;
end
endcase
end
end
endmodule
您的組合always
阻止中的敏感度列表不完整。 改變:
always @(state)
到:
always @*
這可能是合成鎖存器。
在你的組合always
阻塞中使用阻塞賦值。 將<=
更改為=
。
好的綜合和 linting 工具應該會警告您這些構造。
你在這里有各種各樣的問題。
您的第一個 always 塊的敏感度列表不完整。 您只查看state
,但還有許多其他信號需要在那里。 如果您的工具支持它,請always @*
使用always @*
,它會自動生成敏感度列表。 更改此設置,您的代碼將開始模擬,就像在 FPGA 上運行一樣。
這隱藏了代碼的其他問題,因為它會導致信號在錯誤的時間更新。 您已經設法讓您的代碼在模擬器中運行,但這是基於謊言。 謊言是R_A
、 R_B
、 prev
、 count
和Mul_Result
只依賴於狀態的變化,但有更多的信號是該邏輯的輸入。
您已經陷入了 Verilog 關鍵字reg
創建寄存器的陷阱。 它沒有。 我知道這很愚蠢,但事情就是這樣。 reg
意思是它是一個可以從程序塊分配的變量。 不能將wire
s 分配給程序塊內部。
當您在時鍾程序塊(參見腳注)中分配某些內容時,會創建一個寄存器,例如您的state
變量。 R_A
、 R_B
、 prev
和count
似乎都跨周期保存值,因此需要是寄存器。 我會像這樣更改代碼:
首先,我會創建一組next_*
變量。 這些將包含我們在每個寄存器下一個時鍾中想要的值。
reg [15:0] next_R_B;
reg [7:0] next_R_A;
reg next_prev;
reg [3:0] next_count;
然后我會更改時鍾過程以使用這些:
always @(posedge clk or posedge reset) begin
if(reset==1) begin
state <= start;
R_A <= '0;
R_B <= '0;
prev <= '0;
count <= '0;
end else begin
R_A <= next_R_A;
R_B <= next_R_B;
prev <= next_prev;
count <= next_count;
case (state)
.....
然后最后將第一個進程更改為分配給next_*
變量:
always @* begin
next_R_A <= R_A;
next_R_B <= R_B;
next_prev <= prev;
next_count <= count;
case(state)
start: begin
next_R_A <= Mul_A;
next_R_B <= {8'b00000000,Mul_B};
next_prev <= 1'b0;
next_count <= 3'b000;
Mul_Result <= R_B[7:0];
end
add: begin
case({R_B[0],prev})
2'b00: begin
next_prev <= 1'b0;
end
.....
筆記:
next_
值默認為其前一個值。next_
值永遠不會被讀取,除了時鍾進程next_
值永遠不會被寫入,除非在時鍾過程中。 我還懷疑您希望Mul_Result
成為一條wire
並讓它assign Mul_Result = R_B[7:0];
而不是僅在開始狀態更新的另一個寄存器,但我不確定您要在那里做什么。
reg
,但reg
不一定是寄存器。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.