Verilog 取3个adc数据之和进行3次采样
大家好, 我是用verilog语言编程FPGA的新手。目前,我正在尝试设计固件,以计算3次采样时adc数据的总和。首先,我将在代码中解释一次采样一个adc。当您查看代码时,您可以看到,使用clkr时钟的上升沿和adcIfEnb==1,adc_data将从adcIfData获得值,这是一次采样的数据。在clkr时钟的下一个上升沿和adcIfEnb==1中,该数据存储在iradcTrg中。最后,我将有3个采样的adc_data数据,它们存储在iradcrg中,然后我总结了3个数据。Verilog 取3个adc数据之和进行3次采样,verilog,Verilog,大家好, 我是用verilog语言编程FPGA的新手。目前,我正在尝试设计固件,以计算3次采样时adc数据的总和。首先,我将在代码中解释一次采样一个adc。当您查看代码时,您可以看到,使用clkr时钟的上升沿和adcIfEnb==1,adc_data将从adcIfData获得值,这是一次采样的数据。在clkr时钟的下一个上升沿和adcIfEnb==1中,该数据存储在iradcTrg中。最后,我将有3个采样的adc_data数据,它们存储在iradcrg中,然后我总结了3个数据。 wire-ad
wire-adcIfData[79:0];
规则
始终@(posedge clkr)开始
如果(adcIfEnb)开始
adc_数据[9:0]1 2 3[4 5 6]
因此,我应该如何修复代码以获得我期望的结果,或者在这种情况下,是否有任何文档可以帮助我?如果使用状态机,您的工作将更加轻松。下面是一个小型(且不完整)状态机示例
parameter FIRST_DATA=0, SECOND_DATA=1, THIRD_DATA=2, OUTPUT=3;
reg [2:0] current_state = FIRST_DATA;
reg [9:0] adc_data1;
reg [9:0] adc_data2;
reg [9:0] adc_data3;
reg [11:0] adc_data_sum;
always @ (posedge clk)
begin
// TODO: use proper reset
case (current_state):
FIRST_DATA:
if(adcIfEnb):
current_state <= SECOND_DATA;
SECOND_DATA:
if(adcIfEnb):
current_state <= THIRD_DATA;
THIRD_DATA:
if(adcIfEnb):
current_state <= OUTPUT;
OUTPUT:
if(adcIfEnb):
current_state <= FIRST_DATA;
endcase
end
always @ (negedge clk)
begin
if (current_state == FIRST_DATA && adcIfEnb)
adc_data1 <= adcIfData;
end
always @ (negedge clk)
begin
if (current_state == SECOND_DATA && adcIfEnb)
adc_data2 <= adcIfData;
end
always @ (negedge clk)
begin
if (current_state == THIRD_DATA && adcIfEnb)
adc_data3 <= adcIfData;
end
always @ (negedge clk)
begin
if (current_state == OUTPUT)
adc_data_sum <= adc_data1 + adc_data2 + adc_data3;
end
参数第一个数据=0,第二个数据=1,第三个数据=2,输出=3;
reg[2:0]当前\u状态=第一个\u数据;
reg[9:0]adc_数据1;
reg[9:0]adc_数据2;
reg[9:0]adc_数据3;
reg[11:0]adc\u数据\u和;
始终@(posedge clk)
开始
//TODO:使用正确的重置
案例(当前状态):
第一组数据:
如果(adcIfEnb):
当前状态如果你使用状态机,你的工作会容易得多。下面是一个小型(且不完整)状态机示例
parameter FIRST_DATA=0, SECOND_DATA=1, THIRD_DATA=2, OUTPUT=3;
reg [2:0] current_state = FIRST_DATA;
reg [9:0] adc_data1;
reg [9:0] adc_data2;
reg [9:0] adc_data3;
reg [11:0] adc_data_sum;
always @ (posedge clk)
begin
// TODO: use proper reset
case (current_state):
FIRST_DATA:
if(adcIfEnb):
current_state <= SECOND_DATA;
SECOND_DATA:
if(adcIfEnb):
current_state <= THIRD_DATA;
THIRD_DATA:
if(adcIfEnb):
current_state <= OUTPUT;
OUTPUT:
if(adcIfEnb):
current_state <= FIRST_DATA;
endcase
end
always @ (negedge clk)
begin
if (current_state == FIRST_DATA && adcIfEnb)
adc_data1 <= adcIfData;
end
always @ (negedge clk)
begin
if (current_state == SECOND_DATA && adcIfEnb)
adc_data2 <= adcIfData;
end
always @ (negedge clk)
begin
if (current_state == THIRD_DATA && adcIfEnb)
adc_data3 <= adcIfData;
end
always @ (negedge clk)
begin
if (current_state == OUTPUT)
adc_data_sum <= adc_data1 + adc_data2 + adc_data3;
end
参数第一个数据=0,第二个数据=1,第三个数据=2,输出=3;
reg[2:0]当前\u状态=第一个\u数据;
reg[9:0]adc_数据1;
reg[9:0]adc_数据2;
reg[9:0]adc_数据3;
reg[11:0]adc\u数据\u和;
始终@(posedge clk)
开始
//TODO:使用正确的重置
案例(当前状态):
第一组数据:
如果(adcIfEnb):
当前状态首先评论很少:
1) 我不知道为什么要引入这么多名字奇怪的变量。您只需要一个adc\u缓冲区
和adc\u总和
。iradcrg
与adc\u trg
相同吗?为什么reg语句是空的?为什么adcIfData有80位,而您只使用8个LSB位?我很困惑
2) 由于adc\u sum
将是3的和(adcTrg
在您的情况下),请考虑可能的溢出。如果要添加3个10位数字,adc\u sum
的宽度应该是多少
3) 您不应该先使用异步或同步重置将设计重置为已知状态吗
您可以使用带异步重置的2位计数器和用于包装回0的逻辑:
reg [1:0] adc_buffer_counter_reg;
always @(posedge clkr or negedge rst_n) begin
if (!rst_n)
adc_buffer_counter_reg <= 2'd0;
else if (adcIfEnb) begin
if (adc_buffer_counter_reg == 2'd2) //trigger calc of the sum here
adc_buffer_counter_reg <= 2'd0;
else
adc_buffer_counter_reg <= adc_buffer_counter_reg + 2'd1;
end
reg[1:0]adc\u buffer\u counter\u reg;
始终@(posedge clkr或negedge rst_n)开始
如果(!rst_n)
adc_缓冲区_计数器_reg首先给出几点意见:
1) 我不知道为什么要引入这么多名字奇怪的变量。您只需要一个adc\u缓冲区
和adc\u总和
。iradcrg
与adc\u trg
相同吗?为什么reg语句是空的?为什么adcIfData有80位,而您只使用8个LSB位?我很困惑
2) 由于adc\u sum
将是3的和(adcTrg
在您的情况下),请考虑可能的溢出。如果要添加3个10位数字,adc\u sum
的宽度应该是多少
3) 您不应该先使用异步或同步重置将设计重置为已知状态吗
您可以使用带异步重置的2位计数器和用于包装回0的逻辑:
reg [1:0] adc_buffer_counter_reg;
always @(posedge clkr or negedge rst_n) begin
if (!rst_n)
adc_buffer_counter_reg <= 2'd0;
else if (adcIfEnb) begin
if (adc_buffer_counter_reg == 2'd2) //trigger calc of the sum here
adc_buffer_counter_reg <= 2'd0;
else
adc_buffer_counter_reg <= adc_buffer_counter_reg + 2'd1;
end
reg[1:0]adc\u buffer\u counter\u reg;
始终@(posedge clkr或negedge rst_n)开始
如果(!rst_n)
adc_buffer_counter_reg开始:确保将代码放入stackexchange时正确缩进
第二:我假设您在发布代码之前已经编辑了代码,因为该代码不会编译,例如,顶部有一个浮动“reg”,没有模块声明。
第三:您已经定义了一个wire adcIfData[79:0],我假设您的意思是[9:0]。
第四:您使用了未定义的变量:adc_数据,adc_trg。
第五:我建议你给你的变量起个更有意义的全名,比如:gater_样本,sum_off_样本。
现在让我们看看代码的核心。您需要采集样本并将其转移到30位寄存器中。无需写入“adc_-trg[19:10],adc_-trg[9:0]”adc_-trg[19:0]即可。此外,无需事先将其放入不同的寄存器中。我只想使用:
always @(posedge clkr)
if (adcIfEnb)
iradcTrg[29:0] <= {iradcTrg[19:0],adcIfData[9:0]};
始终@(posedge clkr)
if(adcIfEnb)
iradcrg[29:0]开始:确保将代码放入stackexchange时正确缩进
第二:我假设您在发布代码之前已经编辑了代码,因为该代码不会编译,例如,顶部有一个浮动“reg”,没有模块声明。
第三:您已经定义了一个wire adcIfData[79:0],我假设您的意思是[9:0]。
第四:您使用了未定义的变量:adc_数据,adc_trg。
第五:我建议你给你的变量起个更有意义的全名,比如:gater_样本,sum_off_样本。
现在让我们看看代码的核心。您需要采集样本并将其转移到30位寄存器中。无需写入“adc_-trg[19:10],adc_-trg[9:0]”adc_-trg[19:0]即可。此外,无需事先将其放入不同的寄存器中。我只想使用:
always @(posedge clkr)
if (adcIfEnb)
iradcTrg[29:0] <= {iradcTrg[19:0],adcIfData[9:0]};
始终@(posedge clkr)
if(adcIfEnb)
iradcTrg[29:0]