我有一个问题,关于我正在开发的 AGC/SPI 控制器在我看来奇怪的行为。它是用 Verilog 完成的,针对的是 Xilinx Spartan 3e FPGA。该控制器是一个依赖外部输入来启动的 FSM。 FSM的状态存储在状态寄存器它没有显式初始化,因为我认为未初始化的寄存器将默认为零。当我实现控制器时,FSM 不会运行。监视 SPI 总线时我没有观察到任何活动。为了监控 FSM,我路由了状态寄存器到连接 LED 组的输出总线。这就是这条线分配 data_out = state_reg是在做。但我发现,当我这样做时,FSM 的 AGC/SPI 控制器可以正常运行,正如在 SPI 总线上观察到的那样。似乎正在发生的事情是这样的状态寄存器初始化时处于未确定状态,因此 FSM 永远不会处于任何状态,因此它不会运行。但通过分配状态寄存器到它初始化为的输出00000000正如我从一开始就预期的那样。所以我的问题是,未初始化的寄存器是否应该假定值为 0?通过将未初始化的寄存器分配给输出,是否会强制其假定为零?还是这里发生了其他我不明白的事情?下面是我的代码。我已经评论了分配 *state_reg** 的相关部分输出线[7:0] data_out。我知道这是一个很长的问题,但我真的很想了解我应该期待什么类型的行为。谢谢。
module agc_control
(
input wire [7:0] agc_data,
input wire clk,
input wire agc_start,
input wire AMP_DO,
output reg MOSI,
output reg SCK,
output reg CS_AMP,
output wire inhibit_ADC,
output wire [7:0] data_out
);
//signals
reg [4:0] state_reg,
reg [2:
0] ampclkreg;
reg ampclk;
reg [7:0] agc_data_reg;
reg agc_running;
reg [7:0] data_out_reg;
wire agc_done;
//ampclk generation
always @(posedge clk)
begin
ampclkreg = ampclkreg + 1;
if (ampclkreg == 3)
begin
ampclkreg = 0;
ampclk = ~ampclk;
end
end
always @(posedge clk)
begin
if(agc_start == 1)
begin
agc_running = 1'b1;
agc_data_reg = agc_data;
end
if(agc_done == 1)
begin
agc_running = 1'b0;
end
end
//FSM
always @(posedge ampclk)
begin
if (agc_running == 0)
begin
SCK = 0;
state_reg = 0;
CS_AMP = 1;
end
if (agc_running == 1)
begin
case (state_reg)
0: begin
CS_AMP = 1;
SCK = 0;
state_reg = 1;
end
1: begin
CS_AMP = 0;
MOSI = agc_data_reg[7];
state_reg = 2;
end
2: begin
SCK = 1;
state_reg = 3;
end
3: begin
SCK = 0;
MOSI = agc_data_reg[6];
state_reg = 4;
end
4: begin
SCK = 1;
state_reg = 5;
end
5: begin
SCK = 0;
MOSI = agc_data_reg[5];
state_reg = 6;
end
6: begin
SCK = 1;
state_reg = 7;
end
7: begin
SCK = 0;
MOSI = agc_data_reg[4];
state_reg = 8;
end
8: begin
SCK = 1;
state_reg = 9;
end
9: begin
SCK = 0;
MOSI = agc_data_reg[3];
state_reg = 10;
end
10:begin
SCK = 1;
state_reg = 11;
end
11:begin
SCK = 0;
MOSI = agc_data_reg[2];
state_reg = 12;
end
12:begin
SCK = 1;
state_reg = 13;
end
13:begin
SCK = 0;
MOSI = agc_data_reg[1];
state_reg = 14;
end
14:begin
SCK = 1;
state_reg = 15;
end
15:begin
SCK = 0;
MOSI = agc_data_reg[0];
state_reg = 16;
end
16:begin
SCK = 1;
state_reg = 17;
end
17:begin
CS_AMP = 1;
state_reg = 18;
end
18:begin
SCK = 0;
state_reg = 19;
end
19:begin
state_reg = 19;
end
default: state_reg = 19;
endcase
end
end
//retrieve previous vlaues
always @(posedge clk)
begin
case(state_reg)
2: begin
if (ampclkreg == 2)
data_out_reg[7] = AMP_DO;
end
4: begin
if (ampclkreg == 2)
data_out_reg[6] = AMP_DO;
end
6: begin
if (ampclkreg == 2)
data_out_reg[5] = AMP_DO;
end
8: begin
if (ampclkreg == 2)
data_out_reg[4] = AMP_DO;
end
10:begin
if (ampclkreg == 2)
data_out_reg[3] = AMP_DO;
end
12:begin
if (ampclkreg == 2)
data_out_reg[2] = AMP_DO;
end
14:begin
if (ampclkreg == 2)
data_out_reg[1] = AMP_DO;
end
16:begin
if (ampclkreg == 2)
data_out_reg[0] = AMP_DO;
end
endcase
end
//output wire [7:0] data_out--to top module to drive 7 LEDs and display state_reg
assign data_out = state_reg;
assign agc_done = (state_reg == 19);
assign inhibit_ADC = (agc_running == 1);
endmodule
我在 FPGA 方面回答(我对 Xilinx FPGA 拥有最多的经验);我不同意蒂姆的回答。
当FPGA被编程和初始化时,many内部资源被初始化为已知状态。这包括所有触发器和块公羊。通过在整个设计中添加毯子重置逻辑,您may如果您可以依靠初始化为已知状态的内部元素,那么它会比需要的复杂得多。高扇出复位网络会使路由器的设计实现变得更加困难,并且将设计映射到切片也会因您选择的复位(尤其是异步复位)而变得复杂。
我的建议:
- 使用寄存器的初始化值。仔细检查 Xilinx XST 文档,了解您所使用的版本是否支持语法。与广泛持有的看法相反,在大多数情况下都会遵守初始化值。这样做的好处是芯片的初始状态将与模拟的初始状态相匹配。
- 仅重置必要的控制信号并保留数据路径寄存器,以实现更有效的映射(例如,将管道映射到移位寄存器)。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)