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

移位运算与乘法

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 回复 分享
发布于 2025-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

相关推荐

关于“实习生工资多少才算正常”,其实并没有一个放之四海而皆准的标准,但如果结合一线城市的生活成本、工作强度以及实习本身创造的价值来看,我个人认为6000&nbsp;元左右应当是一个基本及格线,也就是每天&nbsp;200&nbsp;多元。如果能达到&nbsp;300、400&nbsp;元一天,甚至更高,那无疑是更理想的状态。首先,从现实成本看,房租、通勤、餐饮几乎都是刚性支出。低于这个水平的实习,往往意味着实习生需要用家庭或存款“倒贴”工作,这在长期来看并不合理。实习本质上是学习,但并不等于“廉价劳动力”,更不应该是经济压力的来源。其次,愿意给实习生更高薪资的公司,通常不会是差公司。这至少说明两点:一是公司资金相对充足,不是靠压缩人力成本勉强维持;二是公司认可实习生的价值,希望你真正参与业务、创造产出,而不是只做边角料工作。很多高薪实习往往伴随着更规范的培养体系、更高的信息密度和更真实的项目经验。当然,高工资并不等于一切,但它往往是一个重要信号。能给到&nbsp;300、400&nbsp;元一天甚至更多的公司,往往对效率、能力和长期发展更有追求,也更可能处在一个有前景的赛道中。总结来说,实习工资不仅是钱的问题,更是公司态度、实力和发展前景的体现。在条件允许的情况下,争取一份“付得起你时间”的实习,本身就是一种理性选择。
北国牛马:你是不是忘了你一周只能上五天班,月薪6000那你日薪就得300了,日薪200一个月也就4000,也就刚好覆盖生活成本了
实习生工资多少才算正常?
点赞 评论 收藏
分享
评论
96
11
分享

创作者周榜

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