reg vld = 0;reg in;reg out;always @(posedge clk) begin if (in) begin vld <= 1; end if (vld) begin out <= 1; endend 这个代码明明in有效,但是后面if vld判断没有成立,是什么原因?给出解决代码
时间: 2024-03-26 14:42:12 浏览: 13
在这个代码中,如果输入信号in在时钟上升沿到来时为1,则vld寄存器会在同一时钟周期内被赋值为1。然而,在同一个时钟周期内,如果在in有效的情况下,vld被赋值为1,那么在下一个时钟上升沿到来之前,if语句判断中的vld寄存器的值仍然为0。因此,out寄存器的值不会被赋值为1。
为了解决这个问题,可以使用非阻塞赋值语句(<=)来更新vld寄存器的值。这样,在同一时钟周期内,vld寄存器的值会立即被更新为1,从而能够在下一个时钟上升沿到来时被正确地判断。
下面是修改后的代码:
```
reg vld = 0;
reg in;
reg out;
always @(posedge clk) begin
vld <= 0; // 在每个时钟周期的开始将vld寄存器的值赋为0
if (in) begin
vld <= 1;
end
if (vld) begin
out <= 1;
end
end
```
在这个修改后的代码中,vld寄存器的值在每个时钟周期的开始时被赋值为0。因此,如果在时钟上升沿到来时,in信号为1,则vld寄存器会被立即赋值为1。接着,由于使用了非阻塞赋值语句(<=),vld寄存器的值会立即被更新为1,从而使得在下一个时钟上升沿到来时,if语句判断中的vld寄存器的值为1,out寄存器的值被正确地赋值为1。
相关问题
Verilog中 下面代码:reg vld;reg in;reg out;always@(posedge clk)begin if(in)vld<=1; if (vld))out<= 1;end 上面代码in有效,为什么out没有赋值,应该怎么修改,给出代码
根据上述Verilog代码,当时钟上升沿到来时,如果输入信号in为1,则将vld寄存器赋值为1。接着,如果vld寄存器的值为1,则将out寄存器赋值为1。
但是,代码中没有明确指定vld寄存器的初始值,因此在模拟时会受到vld寄存器的随机值的影响,导致out寄存器的输出值不确定。为了解决这个问题,可以将vld寄存器的初始值赋为0,或者使用非阻塞赋值语句(<=)来更新vld寄存器的值。
下面是修改后的代码:
```
reg vld = 0;
reg in;
reg out;
always @(posedge clk) begin
if (in) begin
vld <= 1;
end
if (vld) begin
out <= 1;
end
end
```
在这个修改后的代码中,vld寄存器的初始值被赋为0,而非阻塞赋值语句(<=)被用来更新vld寄存器的值。这样就能确保out寄存器的输出值是可预测的。
请设计一个输入8bits数据的开根运算器,条件:(1)输入不连续,两个输入数据至少间隔5个时钟周期,(2)消耗资源尽可能少,(3)输出结果保留整数 部分并完成四舍五入; module sqrt8dat( input clk, input rst_n, input [7:0] din, input din_vld, output wire [3:0] dout, output wire dout_vld ); 请将代码补充完整
根据条件,我们可以采用流水线的方式,将8bits数据输入分为两个阶段,每个阶段需要消耗一些资源,同时满足了输入不连续的条件。
第一阶段:将输入数据扩展为16bits并进行加法运算,得到一个8bits的中间结果。这个阶段需要用到一个16bits的加法器。
第二阶段:对中间结果进行开根运算,得到4bits的整数部分。这个阶段可以采用查表法,预先计算好所有可能的8bits数据的整数部分,并存储在一个ROM中。每个8bits数据对应一个4bits的整数部分,可以直接输出。这个阶段需要用到一个ROM。
最后,对整数部分进行四舍五入,得到最终的输出结果。这个过程可以用一个简单的比较器实现。
下面是完整的代码实现:
```verilog
module sqrt8dat(
input clk,
input rst_n,
input [7:0] din,
input din_vld,
output reg [3:0] dout,
output reg dout_vld
);
// 中间结果寄存器
reg [15:0] mid_res;
// 整数部分ROM
reg [3:0] int_part_rom [255:0];
// 比较器阈值
parameter [3:0] cmp_thr = 8'h8;
// ROM初始化
initial begin
for (int i = 0; i < 256; i = i + 1) begin
int_part_rom[i] = $clog2(i);
end
end
always @(posedge clk or negedge rst_n) begin
if (~rst_n) begin
mid_res <= 0;
dout_vld <= 0;
dout <= 0;
end
else if (din_vld) begin
mid_res <= {8'b0, din} + mid_res;
end
else begin
mid_res <= mid_res;
end
end
always @(posedge clk or negedge rst_n) begin
if (~rst_n) begin
dout_vld <= 0;
dout <= 0;
end
else if (din_vld) begin
if ($unsigned(mid_res) < (16'h100)) begin
dout_vld <= 1;
dout <= int_part_rom[$unsigned(mid_res[15:8])];
if ((mid_res[7:0] >= cmp_thr) || ((mid_res[7:0] == cmp_thr-1) && (dout[0] == 1'b1))) begin
dout <= dout + 1;
end
end
else begin
dout_vld <= 0;
dout <= 0;
end
end
else begin
dout_vld <= 0;
dout <= 0;
end
end
endmodule
```