LV4_移位运算与乘法
题目来源于牛客网
[牛客网在线编程_Verilog篇_Verilog快速入门 (nowcoder.com)](https://www.nowcoder.com/exam/oj?page=1&tab=Verilog篇&topicId=301)
题目
题目描述:
已知d为一个8位数,请在每个时钟周期分别输出该数乘1/3/7/8,并输出一个信号通知此时刻输入的d有效(d给出的信号的上升沿表示写入有效)
信号示意图:
波形示意图:
输入描述:
输入信号 d, clk, rst
类型 wire
在testbench中,clk为周期5ns的时钟,rst为低电平复位
输出描述:
输出信号 input_grant out
类型 reg
状态机
在Verilog中,可以使用always
语句和case
语句来实现状态机。
首先,声明一个状态寄存器state_reg
,用于存储当前状态的值。状态寄存器通常是一个有限状态机中的关键变量。
reg [2:0] state_reg;
在always @(posedge clk)
块中,使用case
语句根据当前的状态值执行相应的操作。在时钟的上升沿触发该always
块。
always @(posedge clk) begin
case (state_reg)
// 根据当前状态执行相应操作
// 每个状态对应一个case
// 每个case中描述该状态下的行为
endcase
end
在每个case中,根据当前的状态值执行相应的操作。每个case对应一个状态,并描述在该状态下的行为。
always @(posedge clk) begin
case (state_reg)
// 状态1
2'd0: begin
// 在状态1执行的操作
// 可以包括信号的赋值、状态变迁等
end
// 状态2
2'd1: begin
// 在状态2执行的操作
end
// 状态3
2'd2: begin
// 在状态3执行的操作
end
default: begin
// 默认情况下的操作,当状态寄存器的值不匹配任何已定义的状态时执行
end
endcase
end
代码
`timescale 1ns/1ns
module multi_sel(
input [7:0]d ,
input clk,
input rst,
output reg input_grant,
output reg [10:0]out
);
//*************code***********//
/*代码思路:使用状态机,进行逻辑跳转。可以借此题来练习状态机
1.声明状态寄存器
2.状态之间的转换
3.每个状态执行的操作
将乘法改为移位来计算,可以节省资源*/
//声明参数,状态寄存器
parameter IDLE = 3'd0; //空状态
parameter M1 = 3'd1; //M1时,输入有效(input_grant=1)
parameter M3 = 3'd2;
parameter M7 = 3'd3;
parameter M8 = 3'd4;
reg [2:0] current_state;
reg [2:0] next_state;
reg [7:0] d_tool; //此变量是存储输入有效时d的值
//状态之间的转换
always @(posedge clk or negedge rst) begin
if(!rst)
current_state <= IDLE;
else
current_state <= next_state;
end
//不同状态所要执行的操作
always @(*) begin //和时钟、复位无关
case (current_state)
IDLE : begin
input_grant <= 0;
out <= 0;
next_state <= M1;
end
M1 : begin
input_grant <= 1;
out <= d_tool;
next_state <= M3;
end
M3 : begin
input_grant <= 0;
out <= (d_tool << 2'd2) - d_tool;
next_state <= M7;
end
M7 : begin
input_grant <= 0;
out <= (d_tool << 2'd3) - d_tool;
next_state <= M8;
end
M8 : begin
input_grant <= 0;
out <= (d_tool << 2'd3);
next_state <= M1;
end
default : begin
input_grant <= 0;
out <= 0;
next_state <= IDLE;
end
endcase
end
//输入有效数据 d_tool 和实际的输入 d 的关系
always @(posedge clk or negedge rst) begin
if(!rst)
d_tool <= 0;
else begin
if(current_state == IDLE)
d_tool <= d;
else if(current_state == M8)
d_tool <= d;
else
d_tool <= d_tool;
end
end
//*************code***********//
endmodule