牛客网Verilog快速入门题目收获——移位运算与乘法(VL4)

题目要求:
已知d为一个8位数,请在每个时钟周期分别输出该数乘1/3/7/8,并输出一个信号通知此时刻输入的d有效(d给出的信号的上升沿表示写入有效)
知识储备:
如何实现对一个8位数d乘以1/3/7/8倍数。
采用移位和拼接的方式来实现。


移位

移位都默认补0,左移低位补0,表示乘法,右移高位补0,表示除法。

位拼接

例:a = 2’b10 ; b = 3’b011 ; 那么:
c = {a,b} = 5’b10011
d = {2’b00,b} = 5’b00011
复制+拼接
e = {{2{a}},b} =7’b1010 011

采用移位运算符号实现乘除法:
a = b<<1,左移一位,表示乘以2
a = b>>1,右移一位,表示除以2

- 如何遇到奇数的乘除法怎么办?
进行拆分,比如说乘以3,即可拆分成 a + a2 ;
比如说乘以7,即可拆分成 a + a
2 + a*4 ;


至此,即可来看所给的题目。

信号示意图:
input_grant 表示输入数据d有效
在这里插入图片描述
波形示意图:
通过波形可看到,输入数据d分别为 143 ,7 ,6 ,128 ,129
但是对应看输出out发现,四种情况的乘法运算 忽略了 d =6 ,因为d = 6 的时候,上一个输入数据d = 7 还没有计算完成,同时d = 6 的时候,对应的input_grant信号为低电平,说明d = 6 数据的输入是无效的,从而没有将其进行四种情况的乘法计算。
在这里插入图片描述
由于我们需要对输入数据进行四种乘法运算,所以需要用到移位拼接操作,另外四种情况可以通过case语句来实现,case(控制表达式),其中控制表达式可采用计数器,设计计数器来表示四种情况,第一次计算,第二次计算,第三次第四次计算。

当我在进行计数器设计的时候,我的想法是不仅要设计计数器,还要让它满四次清零,否则会一直计数,后来发现这种想法和操作多此一举,因为定义的计数器是2位的,所以最多只能计数四次,0,1,2,3,当四次计数完成后,也会继续0开始。

关于case语句里面写什么?

  • 每次情况下的输出是多少(也就是该输出是乘以1/3/7/8中的哪一个)。
  • 引入变量d_reg来寄存d的数据,防止进行多次不同乘法的时候d数值改变。
  • input_grant 作为有效信号,要搞清楚其输出的值什么时候是,什么时候是0,因为一个数据计算四次,然后对应接收的下一个数据才是有效的,才可进行下一次计算,因此每第一次乘法运算的时候,input_grant= 1,其余情况为0,所以需要将此信号进行相应的输出。

如下是Verilog代码:

`timescale 1ns/1ns
module multi_sel(
input [7:0]d ,
input clk,
input rst,
output reg input_grant,
output reg [10:0]out
);
//*************code***********//

reg [1:0] cnt;
    
//设计一个计数器,数据有效则开始计数
always @ (posedge clk or negedge rst)begin  
    if(!rst)
        cnt <= 2'b0;
    else 
        cnt <= cnt + 2'b1; 
end
reg [10:0] d_reg;
always @ (posedge clk or negedge rst)begin
    if(!rst)begin
            out <= 11'b0;
            input_grant <= 1'b0;
            d_reg <= 8'b0;
    end
        else begin
            case(cnt)
                2'd0: begin
                    out  <= d;  //乘以1倍数
                    d_reg <= d;  
                    input_grant <= 1'b1;
                end
                2'd1: begin
                    out <=  d_reg + {d_reg,1'b0}; //乘以3倍数
                    //out <=  d_reg + (d_reg<<1); //偶数倍乘法,可用拼接,也可用移位
                    input_grant <= 1'b0;
                end
                2'd2: begin
                    out <= d_reg + {d_reg,1'b0} + {d_reg,2'b00} ; //乘以7倍数
                    input_grant <= 1'b0;
                end
                2'd3: begin
                    //out <=  {d_reg,3'b000} ; //乘以8倍数
                    out <=  d_reg << 3 ;
                    input_grant <= 1'b0;
                end
                default:out <= d_reg;
            endcase 
        end
end
//*************code***********//
endmodule
  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Fighting_FPGA

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值