题解 | #移位运算与乘法#
移位运算与乘法
https://www.nowcoder.com/practice/1dd22852bcac42ce8f781737f84a3272
移位运算与乘法中有两个点需要理解
- 如何计算乘法?
-
先解决问题一,乘法运算其实很好理解,因为数据都为二进制输出。假设现在有一个二进制数为3‘b111,对应的十进制数为7,如果往二进制后添加一位将二进制数从3‘b111变为4’b1110,对应的十进制数则从7变为十进制的14.
由此可知,通过在末位加0的方式可以实现二进制数的乘法运算,移位的方式也是可行的,verilog在移位计算中,默认对空缺的位置补0。同前一个方法一致。
末尾补零,采用拼接的方法,例如对3‘b111进行乘二操作,{3’b111,1‘b0},乘7操作{3’b111,3‘b000} - 3'b111.
移位法,例如乘二操作(3’b111<<1),乘七操作(3‘b111<<3) - 3'b111。
问题二,通过波形分析,有以下几个点;
一、所有信号在时钟上升沿触发。
二、rst是低位置零。
三、input_grant的信号只有在out = d 的时候为0,其他时刻皆为1.
四、out值对读入的d输入值进行四个周期的乘法计算后才会再次读取下一个d值。在乘法计算的四个周期内,d值的变化对out值没有影响。
根据以上分析,可知:
一、在写代码时需要考虑对d的值进行一个保存,保存的值经过四个周期后再次读入d的值。循环往复。
二、需要对四个周期进行一个额外的计时,以四个周期为一个大的周期,不同周期对应的乘法方式不同。
三、每次乘法计算时只乘以保存的值,并不读取d的值。
以上就是整个题的分析,最后贴以下代码。
`timescale 1ns/1ns module multi_sel( input [7:0]d , input clk, input rst, output reg input_grant, output reg [10:0]out ); //*************code***********// reg [1:0] cnt; reg [7:0] din; always @(posedge clk or negedge rst) begin if(!rst) begin out <= 11'b0;input_grant <= 1'b0;din <= 8'b0;cnt <= 2'b0; end else begin cnt <= cnt + 1'b1; case (cnt) 2'b00: begin din <= d;out <= d; input_grant <= 1'b1; end 2'b01: begin out <= din + {din,1'b0};input_grant <= 1'b0; end 2'b10: begin out <= {din,3'b000} - din;input_grant <= 1'b0; end 2'b11: begin out <= {din,3'b000};input_grant <= 1'b0; end endcase end end //*************code***********// endmodule