基于Verilog语言分模块设计32位可逆计数器及模块设计中的一些错误!!!

基于Verilog语言分模块设计32位可逆计数器及模块设计中的一些错误!!!

32位可逆计数器分模块设计:

模块划分:

在这个32位可逆计数器中,有加法计数功能和减法计数功能。所以,可以把加法计数放一个模块;同时把减法计数放一个模块;最后,同名顶层模块调用这两个模块实现可逆计数器的设计。
其他:采用同步复位;复位的值可以控制;减法计数一旦计数到0,输出一个标志位;加法计数一旦计数到最大值,输出一个标志位。

模块框图如下:

设计框图

加法计数模块设计:

module add (
	input	clk,
	input	rst,
	input	[31:0]	data,
	output	reg	[31:0]	out,
	output	reg	[31:0]	q);

always @ (posedge clk )//这里的时钟和复位的关系:同步关系
	begin
		if(!rst)//复位信号必须要等待时钟的上升沿
			out<=data;
		else if (out=={
    
    8{
    
    4'b1111}})
		begin
			q <= {
    
    {
    
    30{
    
    1'b0}},2'b01};//输出标志位
			out <= data;
		end
		else
		begin
			out<=out+1'b1;
			q <= {
    
    {
    
    30{
    
    1'b0}},2'b00};
		end
	end	
endmodule

减法计数模块设计:

module sub (
	input	clk,
	input	rst,
	input	[31:0]	data,
	output	reg	[31:0]	out,
	output	reg	[31:0]	q);

always @ (posedge clk )
	begin
		if(!rst)
			out<= data;  //- initial
		else if (out=={
    
    8{
    
    4'b0000}})
		begin
			q <= {
    
    {
    
    30{
    
    1'b0}},2'b10};
			out <= data;
		end

		else
		begin
			out<=out-1'b1;
			q <= {
    
    {
    
    30{
    
    1'b0}},2'b00};
		end
	end	
endmodule

顶层模块设计:

//采用新的编码方式(公司要求)
//当然,大家随意。喜欢就好。这种module的写法更加简单。不过实例化的时候就有一点不爽!!!
module top (
	input clk                   ,
	input rst                   ,
	input en                    ,
	input [31:0] data1          ,
	input [31:0] data2          ,
	output  reg [31:0] out_come  ,
	output  reg [31:0] y        );
//模块之间的连接必须是线网型(wire)
wire  [31:0] a1;
wire  [31:0] b1;
wire  [31:0] a2;
wire  [31:0] b2;
//模块调用不可以放在always块中,这样会报错误。
//if	case	等行为级语句必须放在always中,不然也会报错。意思就是if	case中的条件错误。反正错误就是这样的。
//错误是检测不到希望调用的模块。
	add  u_add_0 (.clk(clk),.rst(rst),.data(data1),.out(a1),.q(b1));
	sub  u_sub_0 (.clk(clk),.rst(rst),.data(data2),.out(a2),.q(b2));
//虽然输出类型是reg,但是赋值方式是阻塞赋值,所以电路是组合逻辑电路。
//always中的敏感列表需要写够;不然会出现错误的逻辑。
//例如:always @ (en)	这样只是看到了表象的“输入(en)”,忽视了“其他输入”,比如a1,a2,b1.b2。
always @ (en or a1 or a2 or b1 or b2)
//always @ (*)		//当敏感列表不清楚时,可以使用这个方式写。但是,这样不利于别人读代码。
	if(en)
	begin
		out_come = a1 ;
		y        = b1 ;
	end
	else
	begin
		out_come = a2 ;
		y        = b2 ;
	end

endmodule

32位可逆计数器仿真平台的搭建:

testbench:

module top_tb;
reg		clk,rst,en;
reg	[31:0]	data1,data2;
wire	[31:0]	out_come;
wire	[31:0]	y;
top t1 (clk,rst,en,data1,data2,out_come,y);
initial
begin
	clk=0;rst=0;en=1;
	data1={
    
    {
    
    7{
    
    4'b1111}},4'b0000};
	data2={
    
    {
    
    7{
    
    4'b0000}},4'b0111};
#20	rst=1;
#50	rst=0;
#240	rst=1;
#20	en=0;rst=0;
#20	rst=1;
#240	rst=0;
#20	$finish;
end
//时钟周期为12个时间单位
always	#6 clk=~clk;

endmodule


仿真结果:

整体仿真图
整体仿真
局部仿真
局部仿真

总结:

就是一些错误和需要注意的东西而已。

感想:

本次写这个博客就是因为我发现,自己再模块之间的调用上存在一些问题,新手(如我)很容易犯的一些错误。当自己再写代码的时候,调程序自己调到奔溃。这时的我就像是溺水的人看见什么都想抓,谁知抓住了稻草,但是这样有什么用,还不是淹死了。所以说,最基本的规则不能打破,老老实实练习代码,修改代码,调试程序,看波形。根基不稳、地动山摇。

猜你喜欢

转载自blog.csdn.net/yixiaoyaobd/article/details/108137334