题目链接 : 移位运算与乘法_牛客题霸_牛客网
分析
采用状态机设计,那么算上复位状态一共五个状态即可,状态间的转换是随着时钟直接转换的,即除去复位状态后的四个状态循环。
但是在 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