Verilog写的简单数据统计模块,仿真却总是出错
时间:10-02
整理:3721RD
点击:
写了一个简单的数据统计模块,采用内部ip生成的 single port RAM,
Read状态读入原值,Write状态加1后存入原地址,够10个后输出统计值。
但是仿真结果输出为0,addr为红色未知状态,请高手看看是什么原因。
verilog代码如下。
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
module histo_count(
clk,
wea,
rst_n,
Result
);
parameter WIDTH = 8;
parameter DEPTH_BITS = 8;
input clk;
input wea;
input rst_n;
output [7:0]Result;
// output register
reg [WIDTH-1:0] addr;
wire [DEPTH_BITS-1:0] d_out;
reg [DEPTH_BITS-1:0] d_in;
reg all_output = 0;
//INSTANTIATION
si_ram s_ram_1(
.clka(clk), // input clka
.wea(wea), // input [0 : 0] wea
.addra(addr), // input [7 : 0] addra
.dina(d_in), // input [7 : 0] dina
.douta(d_out) // output [7 : 0] douta
);
//FSM
parameter [4:0] // single hot
IDLE = 5'b00001,
Read = 5'b00010,
Write = 5'b00100,
Read_all = 5'b01000,
Save_all = 5'b10000;
reg [4:0]current_state;
reg [4:0]next_state;
reg [7:0] i = 8'b0; // counter
reg [7:0] k = 8'b0; // counter
always @ (posedge clk or negedge rst_n)
if(!rst_n)
current_state <= IDLE;
else
current_state <= next_state;
always @ (*) //to supress warning, use * in the sensative list.
begin
case(current_state)
IDLE: begin
if(!rst_n)
next_state = IDLE;
else
next_state = Read;
end
Read: begin
if (i==10)begin
all_output = 1;
next_state = Read_all;
end
else begin
addr <= d_in;
next_state = Write;
end
end
Write: begin
if(wea) // do i need this if?
d_in <= d_out + 1;
i = i + 1;
next_state = Read;
end
Read_all: begin
if(k==10) begin
k = 0;
next_state = IDLE;
end
else begin
addr <= k;
k = k + 1;
next_state = Read_all;
end
end
default: next_state = IDLE;
endcase
end
assign Result = (all_output)? d_out : 0;
endmodule
Read状态读入原值,Write状态加1后存入原地址,够10个后输出统计值。
但是仿真结果输出为0,addr为红色未知状态,请高手看看是什么原因。
verilog代码如下。
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
module histo_count(
clk,
wea,
rst_n,
Result
);
parameter WIDTH = 8;
parameter DEPTH_BITS = 8;
input clk;
input wea;
input rst_n;
output [7:0]Result;
// output register
reg [WIDTH-1:0] addr;
wire [DEPTH_BITS-1:0] d_out;
reg [DEPTH_BITS-1:0] d_in;
reg all_output = 0;
//INSTANTIATION
si_ram s_ram_1(
.clka(clk), // input clka
.wea(wea), // input [0 : 0] wea
.addra(addr), // input [7 : 0] addra
.dina(d_in), // input [7 : 0] dina
.douta(d_out) // output [7 : 0] douta
);
//FSM
parameter [4:0] // single hot
IDLE = 5'b00001,
Read = 5'b00010,
Write = 5'b00100,
Read_all = 5'b01000,
Save_all = 5'b10000;
reg [4:0]current_state;
reg [4:0]next_state;
reg [7:0] i = 8'b0; // counter
reg [7:0] k = 8'b0; // counter
always @ (posedge clk or negedge rst_n)
if(!rst_n)
current_state <= IDLE;
else
current_state <= next_state;
always @ (*) //to supress warning, use * in the sensative list.
begin
case(current_state)
IDLE: begin
if(!rst_n)
next_state = IDLE;
else
next_state = Read;
end
Read: begin
if (i==10)begin
all_output = 1;
next_state = Read_all;
end
else begin
addr <= d_in;
next_state = Write;
end
end
Write: begin
if(wea) // do i need this if?
d_in <= d_out + 1;
i = i + 1;
next_state = Read;
end
Read_all: begin
if(k==10) begin
k = 0;
next_state = IDLE;
end
else begin
addr <= k;
k = k + 1;
next_state = Read_all;
end
end
default: next_state = IDLE;
endcase
end
assign Result = (all_output)? d_out : 0;
endmodule
状态机里always @ (*) ,为啥用这个
这个是新写法,相当于把所有的敏感列表都放进去。
TB代码呢?
仿真时,把current_state、next_state、i、k、all_output、addr、din等变量都添加到仿真波形中,你再根据current_state、next_state、i、k来分析FSM代码,查看是否逻辑上是否有问题!你会发现问题的!
你都已经发现addr是红线了,继续往前推理就是了。addr《=d_in,显然是由d_in决定的,而d_in在上电的时候没有确定值,当然不行了。
写代码的时候,reg最好都赋初值,或者rst的时候赋值
没有复位
