数字IC设计、验证、FPGA笔试必会 - Verilog经典习题 (四)移位运算与乘法
????声明:
????博主主页:王_嘻嘻的CSDN博客
????未经作者允许,禁止转载
????系列专栏:牛客Verilog习题集
????推荐一个IC、FPGA新手入门的好网站:????快 点 击 进 入 学 习 吧
继续整理牛客网经典Verilog习题讲解,牛客网里除了最新的Verilog题库还有其它领域的经典笔试、面试题,大家快和我一起刷起来吧 点 击 跳 转
题目
已知d为一个8位数,请在每个时钟周期分别输出该数乘1/3/7/8,并输出一个信号通知此时刻输入的d有效(d给出的信号的上升沿表示写入有效)
分析:
本题理解起来应该不难,主要是练习时序电路的控制。需要注意的是out需要连续输出第一拍采集数据的1/3/7/8倍,而在这4拍的输出中,所有的输入是忽略的。根据clk上升沿虚线,可以看出,对输入采样的第一拍就开始out有效。
例如d输入128时,还处于第三个数据的1倍输出。
题解:
在完成这题时,可能很多新手分析不清时序,其实我们只需要抓住时序的重点,再围绕展开即可。
本题的重点其实在于连续输出4拍数据,且连续不断的输出;至于哪一拍输出grant_vld或是每一拍数据怎么处理都是后话了。
- 那么是否可以采用一个计数器来记录节拍呢,有了这个节拍,输出数据就好处理了;
- 如下列代码所示,如果cnt(计数器)复位值为0,那么复位释放后,第一拍有效时cnt=1,所以cnt的周期为1、2、3、0的循环;
- 所以grant_vld永远在cnt=1时有效即可;
- 并根据cnt值的区别进行不同的数据操作;
- 而为了忽略输入信号中途改变的影响,需要在每次周期结束后,采样输入d,作为下一周期的数据。
注意:虽然题目描述的是乘法,但其实只有3、7不是2的幂次,且3=4-1,7=8-1。完全可以通过移位加减来完成,不需要使用更费资源的乘法,当然如果倍数过于复杂,采用乘法也是不错的,hhhhh。
`timescale 1ns/1ns
module multi_sel(
input [7:0]d ,
input clk,
input rst,
output input_grant,
output reg [10:0]out
);
//*************code***********//
reg [1:0] cnt; //用来计数连续输出的4次数据
reg [7:0] d_tmp; //第一拍数据采集并保存
always @(posedge clk or negedge rst)begin
if(!rst)
d_tmp[7:0] <= 8'b0;
else if(cnt[1:0]==2'b00)
d_tmp[7:0] <= d[7:0];
end
always @(posedge clk or negedge rst)begin //由于复位为0,所以input_grant有效在cnt=1时,如果需要在cnt=0时,可以自行调整复位值
if(!rst)
cnt[1:0] <= 2'b0;
else
cnt[1:0] <= cnt[1:0] + 2'b1;
end
assign input_grant = cnt[1:0]==2'b01;
always @(*)begin
case(cnt[1:0])
2'b01: out[10:0] <= d_tmp[7:0];
2'b10: out[10:0] <= (d_tmp[7:0]<<2'd2) - d_tmp[7:0];
2'b11: out[10:0] <= (d_tmp[7:0]<<2'd3) - d_tmp[7:0];
2'b00: out[10:0] <= d_tmp[7:0]<<2'd3;
endcase
end
//*************code***********//
endmodule