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

移位运算与乘法

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

题意整理

1、在硬件中进行乘除法运算是比较消耗资源的一种方法,想要在不影响延迟并尽量减少资源消耗,必须从硬件的特点上进行设计。根据寄存器的原理,由于是二进制,所以进位和退位为x2或者/2,同样除7可以使用进位3然后减去本身的做法,这样就将乘除法运算转化为位运算,这是一种比较简单的整数运算处理。

2、 需要给出一个计数器的状态机,注意d输入不是随时有效的,只有在cnt计数为0的那个时钟沿,d输入有效,因此需要设计一个寄存器din,在cnt为0时候锁存d的值

题解主体

根据题意分析,可以得到状态转换:

设输入为d,计数器为cnt

移位运算逻辑:

位运算

1

d

3

(din<<2)-din

7

(din<<3)-din

8

(din<<3)

状态机逻辑:

cnt

out

input_grant

0

直接输出d,并寄存d的值为din

1

1

(din<<2)-din

0

2

(din<<3)-din

0

3

(din<<3)

0

将电路转换成Verilog代码描述如下



reg [1:0]cnt;

reg [7:0]din;


always@(posedge clk or negedge rst) begin

       if(!rst) begin

              cnt <= 0;

              out <= 0;

              input_grant <= 0;

              din <= 0;

       end

       else begin

              cnt <= cnt+1;

              case (cnt)

                     0: begin

                            din <= d;

                            input_grant <= 1;

                            out <= d;

                     end

                     1: begin

                            input_grant <= 0;

                            out <= (din<<2)-din;

                     end       

                     2: begin

                            input_grant <= 0;

                            out <= (din<<3)-din;

                     end

                     3: begin

                            input_grant <= 0;

                            out <= (din<<3);

                     end

              endcase

       end




end


因此实现方式为如下的电路,综合得到:

参考答案

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

reg [1:0]cnt;
reg [7:0]din;

always@(posedge clk or negedge rst) begin
	if(!rst) begin
		cnt <= 0;
		out <= 0;
		input_grant <= 0;
		din <= 0;
	end
	else begin
		cnt <= cnt+1;
		case (cnt)
			0: begin
				din <= d;
				input_grant <= 1;
				out <= d;
			end
			1: begin
				input_grant <= 0;
				out <= (din<<2)-din;
			end		
			2: begin
				input_grant <= 0;
				out <= (din<<3)-din;
			end
			3: begin
				input_grant <= 0;
				out <= (din<<3);
			end	
		endcase
	end



end

endmodule


全部评论
case里要加个default吧?
6 回复 分享
发布于 2022-03-29 14:28
为什么din要在0状态下进行赋值呢?中间值din是什么作用啊?
点赞 回复 分享
发布于 2022-08-12 17:40
cnt不用循环4次后置0吗?
2 回复 分享
发布于 2022-09-06 10:54 安徽
这样做就很简单了,是我想的复杂了,不过结果也是对的
2 回复 分享
发布于 2022-03-12 22:02
不能在cnt为1,2,3的时候直接用d去移位吧。按照题目波形,输入d有可能在这期间变化的,但是输出只针对cnt为0的时候输入的那个数据的处理。在此期间输入的数据不做响应。应该加一个temp_reg 去储存第一个周期输入进来的数据
1 回复 分享
发布于 04-14 21:45 湖北
din是八位的话左移三位如果溢出了应该会有影响,为什么没错呢
1 回复 分享
发布于 2023-10-11 22:37 黑龙江
请问为什么只有case0 的时候才对din赋值,其他case下din的值没有赋值,从哪里来的值计算呢?
1 回复 分享
发布于 2023-08-02 21:13 山东
这样做对吗?假设第一次输入n,在cnt=0的时候输出是n,然后马上第二个周期输入m,那第二个周期输出的就是3m了吧?
1 回复 分享
发布于 2022-10-19 13:48 上海
综合工具会自动优化乘法实现吧,所以移位和直接写*也没什么太大区别
点赞 回复 分享
发布于 2024-05-14 18:34 上海
使用非阻塞赋值din<=d,这几句不就并行执行了吗,那你第一个状态的out是用上一个状态的din算的吧?
点赞 回复 分享
发布于 2024-03-18 19:03 辽宁
寄存输入数据的寄存器位数不用调整吗?
点赞 回复 分享
发布于 2023-07-26 12:19 四川
综合得到的图是在哪里画的呀?
点赞 回复 分享
发布于 2022-10-06 19:18 广东
cnt <= cnt+1;为什么不放在endcase后面呢?这样不会导致rst后的第一个cnt=0呗跳过嘛?
点赞 回复 分享
发布于 2022-05-06 15:18

相关推荐

牛马人的牛马人生:一开始看成了网吧
点赞 评论 收藏
分享
评论
96
11
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务