前三篇文章都是单一模块的设计,然后测试是否来完成特定的功能,不过这种方法只能解决一些简单的问题,所以实际中需要层次花的设计。
这次给大家分享的就是一个层次化的设计,移位寄存器模块+分频模块,然后再用顶层文件把它们组合在一起。
寄存器模块:
module shift1(clk,D,MD,QB);
input clk; //时钟信号
input [7:0] D; //预置数,可以在测试文件中预置,或者在板子上选取
input [1:0] MD; //模式选择数值
output [7:0] QB; //输出的数值
reg [7:0] REG; //定义寄存器类型
always @ ( posedge clk ) begin //对时钟信号上升沿敏感
case (MD) //根据MD的数值,选择模式
2'b01: begin REG[0] <= REG[7] ; REG[7:1] <= REG[6:0]; end //循环左移
2'b10: begin REG[7] <= REG[0] ; REG[6:0] <= REG[7:1]; end //循环右移
2'b00: begin REG <= D; end //加载预置的数值
endcase
end
assign QB[7:0] = REG[7:0]; //把REG中的数值赋给QB
endmodule
分频模块:
记得一开始的十进制可加可减计数器设计中,我们没有用分频模块,而是把时钟模块绑到了一个按键上,然后按一次表示一个时钟,这样很麻烦,引入分频模块就很有必要了。
module div(
input div_rst,
input div_clk, //输出的时钟是100M的
output clk_out
);
reg [30:0] div_q;
reg temp;
always @ (posedge div_clk or posedge div_rst)
begin
if ( div_rst == 0 ) div_q <= 0;
else if( div_q == 50000000) //保证输出的时钟是1s一次的
begin
div_q <= 0; temp <= ~temp;
end
else div_q <= div_q + 1;
end
assign clk_out = temp;
endmodule
顶层文件:
module top(
input clk,
input rst,
input [7:0] D,
input [1:0] MD,
output [7:0] QB);
wire a; //这个a就是把分频模块输出的时钟信号接入到寄存器模块中
div u1 (rst,clk,a); //把模块和顶层连接起来,子模块名字要和之前起的一致
shift1 u2 (a,D,MD,QB);//要注意:这里输入输出端的排布顺序要和在子模块写的顺序一致,否则就会报错。
endmodule
注意:
测试子模块时,比如寄存器模块,那么写完这个模块时,就应该编译,然后写测试文件直接就测试,不要先等写完顶层模块再测试,否则系统会默认测试的是顶层文件,可能会导致没有任何输出产生的情况。
如果没有什么问题,你写顶层文件,然后保存,会出现如下的样子:
表明顶层文件和子模块联系成功,编译没有错误之后,就可以进行下一步了。顶层模块也可以不用测试,如果不写测试文件的话,可以选择 综合下面的:
然后就可以看形成的逻辑图,再比对是否哪里有问题,按照以上程序设计会生成以下的图:
移位寄存器模块如何编写测试文件,可以参考如下链接:
https://blog.csdn.net/weixin_43877139/article/details/88851235
我也写了几篇关于Veirlog的文章,感兴趣的同学可以去看看。该模块链接如下:
https://blog.csdn.net/weixin_43877139/article/category/8778400