题解 | #移位运算与乘法#

移位运算与乘法

https://www.nowcoder.com/practice/1dd22852bcac42ce8f781737f84a3272

1.题目

给定一个输入d[7:0],在每个时钟周期连续输出该值的1/3/7/8倍,并在输出d*1的值时,输出一个周期的有效信号

2. 解题思路

       从给定的参考波形中可以看出,在clk上升沿时检测到d值,out会连续输出4个值(分别为d1/3/7/8倍),连续输出完4个值后,clk会继续采集当前的d值,然后又连续输出4个值。

所以需要注意这种情况:在连续输出4个值的时候,d的值发生了变化,此时clk没有检测到新变化的d值(如波形图中6变化到128,在输出61/3/7/8倍的值时,中途d变化为128,此时的128是不会输出的,只有等连续输出完4个值后才会继续检测新的d

所以可以使用一个计数器来记录输出个数,每当计数满4次后就清0,确保每次连续输出4次。

 

如何实现×1,×3,×7和×8呢,可以考虑使用移位寄存器,通常在最高位不为0的情况下,向左移n位 “<<n“ ,也就是将值扩大为原来的2^n倍;同理最低位不为0情况下,向右移 “>> n” 减少为原来的2^n

3. 模块图

4. 参考波形图

5. 自己绘制的波形图


 

        最初的想法是将d的值进行寄存为d_iniit,然后对寄存的d_int进行移位得到out结果发现当使用时序逻辑时,cnt==0时,d_init还未寄存到d的值(8,此时d_init是初始值0 out输出结果0;同理后面的值也是在cnt==0时没有输出正确的值。

后来我采用组合逻辑完成d_init的赋值, assign d_initial = ( cnt==0) ? d : d_initial;  当cnt == 0时,将d赋值给d_initial,其余时候保持不变。这样因为使用的是组合逻辑,在cnt ==0时会立马赋值给d_init,并且out是时序逻辑,所以正好满足。

       写完之后我学习了其他网友的解题方法,只需要在cnt ==0的时候,直接使用d的值作为out输出即可,并且在cnt ==0时将d寄存在din中,这样在cnt == 1/2/3时,使用的din进行移位计算都是满足要求的

6.仿真波形

6. 参考代码
    reg     [1:0]       cnt;
    wire    [7:0]    d_initial;
    
    assign d_initial = ( cnt==0) ? d : d_initial;

    always@(posedge clk or negedge rst)
        if(!rst)
            cnt <= 2'd0;
        else    if(cnt ==3)
            cnt <= 2'd0;
        else
            cnt <= cnt + 1'b1;
            
     always@(posedge clk or negedge rst)
        if(!rst)
            out <= 4'd0;
        else    
            case(cnt)
                0 : out  <=  d_initial ;
                1 : out  <=  (d_initial <<1) + d_initial;
                2 : out  <=  (d_initial <<3) - d_initial;
                3 : out  <=  d_initial <<3;
            endcase
    
    always@(posedge clk or negedge rst)
        if(!rst)
            input_grant <= 1'd0;
        else    if(cnt == 0)
            input_grant <= 1'b1;
        else    
            input_grant <= 1'b0;

改进之后
    always@(posedge clk or negedge rst)
        if(!rst)    begin
            out <= 48d0;
            d_initial <= 8'd0;
            input_grant  <= 1'b0;
            end
        else    
            case(cnt)
                0 :     begin
                            out  <=  d;
                            d_initial <= d;
                            input_grant  <= 1'b1;
                        end
                1 :     begin
                            input_grant  <= 1'b0;
                            out  <=  (d_initial <<1) + d_initial;
                         end
                2 : out  <=  (d_initial <<3) - d_initial;
                3 : out  <=  d_initial <<3;
            endcase
全部评论

相关推荐

SHC2:关键问题是你这三段实习是三个不同的岗位…你这样子秋招就是只有一段实习的本科生..
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务