在学习Verilog 的 控制器-数据通路建模,就是把寄存器操作和控制寄存器的信号进行分离,使之形成独立的模块:控制模块Control_Unit,数据通路Datapath_Unit,通过顶层模块进行整合。
这是对Gap_finder进行的设计,在给定的16bit二进制数据中找到两个1之间0的个数的最大值。即16’b0100_0011_1111_1111中,返回结果应该是4,16’b0100_0010_0010_0101,返回结果是4,而不是3,2,1。
经过流程分析
控制器代码:
module Gap_finder_Controler #(parameter
idle = 8'b0000_0000,
S_0 = 8'b0000_0001,
S_1 = 8'b0000_0010,
S_2 = 8'b0000_0011,
S_3 = 8'b0000_0100,
S_done = 8'b0000_0101
)(
output reg done,
output reg load_data,clr_data,clr_temp,inc_temp,clr_k,inc_k,
output reg load_gap,
input clk,rst,run,full,bit,max);
reg[7:0] next_state,state;
always@(posedge clk)
if(rst==0)
next_state =idle;
else
state <= next_state;
always @(state,run,full,bit,max)
begin
inc_k=0;
clr_k=0;
inc_temp=0;
clr_temp=0;
clr_data=0;
next_state=0;
done=0;
load_gap=0;
case(state)
idle:begin
inc_k=0;
if(run)
begin
load_data= 1;
next_state =S_0;
end
else
begin
load_data=0;
next_state =idle;
end
end
S_0 : begin
inc_k =1;
if(full)
next_state =S_done;
else if(bit)
next_state =S_1;
else
next_state =S_0;
end
S_1 : begin
inc_k = 1;
if(max)
begin
load_gap=1;
end
else
load_gap=0;
clr_temp=1;
if(full)
next_state =S_done;
else if(bit)
next_state =S_3;
else
next_state =S_2;
end
S_2 : begin
inc_k =1;
inc_temp=1;
if(full)
next_state =S_done;
else if(bit)
next_state =S_1;
else
next_state =S_2;
end
S_3 : begin
inc_k =1;
if(full)
next_state =S_done;
else if(bit)
next_state =S_1;
else
next_state =S_2;
end
S_done: begin
clr_k = 1;
if(max) load_gap = 1;
clr_temp=1;
done= 1;
next_state=idle;
end
default: next_state=idle;
endcase
end
endmodule
数据通路代码:
module data_path_unit(
output reg [3:0]gap,
output full,bit,
output reg max,
input clk,rst,load_data,clr_data,clr_temp,inc_temp,clr_k,inc_k,load_gap,
input [15:0]data);
reg [15:0]datainit;
reg [3:0]temp;
reg [3:0] k;
assign full=(k==15);
assign bit= datainit[k];
always @(posedge clk)
begin
if(rst==0)
begin
temp<=4'b0000;
gap<=4'b0000;
k<=0;
datainit<=0;
max <=0;
$display("rst is done!!!.");
end
else begin
if (load_data)
datainit<=data;
else if (clr_data)
datainit<=0;
if(clr_k) k<=0;
else if(inc_k) k<=k+1;
if(clr_temp) temp<=0;
else if(inc_temp) temp<=temp+1;
if(temp>gap)
max<=1;
else
max<=0;
if(load_gap)
gap<=temp;
else
gap<=gap;
end
end
endmodule
顶层和测试代码:
module tb;
reg clk,rst,run;
wire full,bit,max;
reg [15:0]data;
wire done;
wire load_data,clr_data,clr_temp,inc_temp,clr_k,inc_k,load_gap;
wire [3:0]gap;
Gap_finder_Controler M0(done,load_data,clr_data,clr_temp,inc_temp,
clr_k,inc_k,load_gap,clk,rst,run,full,bit,max);
data_path_unit M1(gap,full,bit,max,clk,rst,load_data,clr_data,
clr_temp,inc_temp,clr_k,inc_k,load_gap,data);
initial
begin
clk=0;rst=0;run=0;
data=16'b0100_1110_0010_0101;
#30 rst = 1;
#30 run = 1;
#20 run = 0;
end
always #10 clk= ~clk;
endmodule
测试结果在,16’b0100_0010_0010_0101中不能检测到第一个1个0gap 和第三个3个0gap。
困惑中。。。
———-2016年11月13日更新————
经过调试,发现Datapath_Unit中max信号(当temp大于gap寄存器的值为1)在always块中,采用非阻塞赋值,延后一个时钟周期,导致运行出错,使用assign赋值后,功能正常。
module data_path_unit(
output reg [3:0]gap,
output full,bit,
output max,//这里修改成wire类型
input clk,rst,load_data,clr_data,clr_temp,inc_temp,clr_k,inc_k,load_gap,
input [15:0]data);
reg [15:0]datainit;
reg [3:0]temp;
reg [3:0] k;
assign full=(k==15);
assign max=(temp>gap);//采用assign赋值语句
assign bit= datainit[k];
always @(posedge clk)
begin
if(rst==0)
begin
temp<=4'b0000;
gap<=4'b0000;
k<=0;
datainit<=0;
//max <=0;
end
else begin
if (load_data)
datainit<=data;
else if (clr_data)
datainit<=0;
if(clr_k) k<=0;
else if(inc_k) k<=k+1;
if(clr_temp) temp<=0;
else if(inc_temp) temp<=temp+1;
if(load_gap)
gap<=temp;
else
gap<=gap;
end
end
endmodule
仿真波形