题目链接 : 移位运算与乘法_牛客题霸_牛客网

分析

采用状态机设计,那么算上复位状态一共五个状态即可,状态间的转换是随着时钟直接转换的,即除去复位状态后的四个状态循环。 alt

但是在 S1 状态时,需要用一个寄存器,记录下当前的 d ,因为之后的时钟周期, d 是会发生改变的。

testbench 参考

(只参照了官方给出的时序图,没有覆盖大多数情况,只能起到一个简单的参考作用,比如快速测试代码基本时序逻辑、快速查看波形)。



`timescale 1ns/1ns
module testbench();
	reg clk=0;
	always #1 clk = ~clk;  // Create clock with period=10
// parameter daclare
    parameter T = 2;
// reg declare
    reg rst ;
    reg [7:0] d;
    wire [10:0] out;
    wire input_grant;
    
    initial begin
        rst = 1'b0;
        d = 8'd143;
        #T    rst = 1'b1;
        #(3*T)    d = 8'd7;
        #(5*T)    d = 8'd6;
        #T        d = 8'd6;
        #T        d = 8'd128;
        #T        d = 8'd129;
        #(5*T) $finish;
    end
    
// instantiate
    multi_sel    u_multi_sel(
        .d(d),
        .clk(clk),
        .rst(rst),
        .input_grant(input_grant),
        .out(out)
    );
//end    
  initial begin
    $dumpfile("out.vcd");
    // This will dump all signal, which may not be useful
    //$dumpvars;
    // dumping only this module
    //$dumpvars(1, testbench);
    // dumping only these variable
    // the first number (level) is actually useless
    $dumpvars(0, testbench);
end  
    
endmodule

状态机方法-参考代码

`timescale 1ns/1ns
module multi_sel(
input [7:0]d ,
input clk,
input rst,
output reg input_grant,
output reg [10:0]out
);
//*************code***********//
// parameter declare
    parameter idle = 0,S1 = 1 , S2 = 2,S3 = 3 , S4 = 4;
// reg parameter
    reg [4:0] state , next_state; // state-machine reg declare;
    reg [7:0] loc_d;
    
    always @(*) begin
        if(!rst) begin
            next_state = 5'b0000_1;
        end
        else begin
            next_state[idle] = ~rst;
            next_state[S1] = state[idle] | state[S4];
            next_state[S2] = state[S1];
            next_state[S3] = state[S2];
            next_state[S4] = state[S3];
        end
    end
    
    always @(posedge clk or negedge rst) begin
        if(!rst) begin
            state = 5'b0000_1;
        end else begin
            state <= next_state;
        end
    end
    
    always @(posedge clk or negedge rst) begin
        if(!rst) begin
            out <= 11'd0;
            input_grant <= 1'b0;
        end else begin
            if(next_state[idle]) begin
                out <= 11'd0;
            end else if(next_state[S1]) begin
                loc_d <= d;
                out <= d;
                input_grant = 1'b1;
            end else if(next_state[S2]) begin
                out <= (out << 1) + loc_d;
//                 out <= loc_d * 3;
                input_grant = 1'b0;
            end else if(next_state[S3]) begin
                out <= (out << 1) + loc_d;
//                 out <= loc_d * 7;
                input_grant = 1'b0;
            end else if(next_state[S4]) begin
                out <= out + loc_d;
//                 out <= loc_d * 8;
                input_grant = 1'b0;
            end
        end
    end
    

//*************code***********//
endmodule