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

移位运算与乘法

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

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

    assign input_grant = (cnt == 2'd1) ? 1'b1 : 1'b0;

    always@(posedge clk, negedge rst) begin
        if(!rst) 
            cnt <= 2'd0;
        else 
            cnt <= cnt + 1'b1;
    end

    always@(posedge clk, negedge rst) begin
        if(!rst)
            out <= 11'd0;
        else if(cnt == 2'b00)
            out <= {3'b000, d_reg};
        else if(cnt == 2'b01)
            out <= ({3'b000, d_reg} << 1) + {3'b000, d_reg};
        else if(cnt == 2'b10)
            out <= ({3'b000, d_reg} << 2) + out;
        else if(cnt == 2'b11)
            out <= d_reg << 3;
        else
            out <= out;
    end

    always@(negedge clk, negedge rst) begin
        if(~rst)
            d_reg <= d;
        else if(cnt == 2'd0)
            d_reg <= d;
    end
endmodule
`timescale  1ns / 1ps

module multi_sel_tb;

// multi_sel Parameters
parameter PERIOD  = 10;


// multi_sel Inputs
reg   [7:0]  d                             = 0 ;
reg   clk                                  = 0 ;
reg   rst                                  = 0 ;

// multi_sel Outputs
wire  input_grant                          ;
wire  [10:0]  out                          ;


initial
begin
    forever #(PERIOD/2)  clk=~clk;
end

multi_sel  u_multi_sel (
    .d                       ( d            [7:0]  ),
    .clk                     ( clk                 ),
    .rst                     ( rst                 ),

    .input_grant             ( input_grant         ),
    .out                     ( out          [10:0] )
);

initial
begin
    d = 8'd143;
    repeat(2)@(negedge clk); 
    #1;     rst = 1'b1;
    #25;    d = 8'd7;
    #50;    d = 8'd6;
    #10;    d = 8'd128;
    #10;    d = 8'd129;
end

endmodule

看了一下大家的解题思路,用状态机去做这个题是一个常见思路。但个人认为这么简单的题目没必要写一个完整的状态机。

在提交代码块中使用一个简单的2位计数器cnt来记录电路的运行状态并执行相应的操作。

需要注意的是提交时网站进行验证时是有延时的,也就是跟modelsim那种信号变化是完全理想不带一点延迟的情况不同,因此在自测代码块中的第37行延迟了1ns才将复位信号拉高以便和网站保持一致。

在提交代码块中,第三十六行在cnt == 0时的时钟下降沿对d进行采样保存到d_reg中,在后续的移位相加中使用d_reg进行操作,防止在没完成一个数的四个乘法操作之前d再次发生变化而产生错误的输出。

划重点:

①之所以在cnt==0时的时钟下降沿对d进行采样是因为上面提到网站提供的testbench中信号的变化是存在延时的。如果改成在cnt==0时的时钟上升沿对d进行采样,并且将自测代码块中第37行的延时1ns去掉的话,在modelsim中进行仿真也是能得到正确的波形的。但这就是完全理想、信号跳变没有延迟的情况,直接提交到网站中就得不到正确的结果从而错误。

②切记移位操作符的优先级比加减操作符低!

全部评论

相关推荐

CADILLAC_:我要用bava 不要用java 了 啊啊啊啊啊啊啊啊啊啊啊
点赞 评论 收藏
分享
迷茫的大四🐶:自信一点,我认为你可以拿到50k,低于50k完全配不上你的能力,兄弟,不要被他们骗了,你可以的
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务