题目:
描述:
已知d为一个8位数,请在每个时钟周期分别输出该数乘1/3/7/8,并输出一个信号通知此时刻输入的d有效(d给出的信号的上升沿表示写入有效)
信号示意图:
波形示意图:
输入描述:
输入信号 d, clk, rst
类型 wire
在testbench中,clk为周期5ns的时钟,rst为低电平复位
输出描述:
输出信号 input_grant out
类型 reg
解答:
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 |
设计代码实现:
在命令行输入g multi.v
,复制下面代码:
`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
验证平台实现:
在命令行敲入 g multi.sv
,然后复制下面代码:
`timescale 1ns/1ps
module tb_top();
logic [7:0] D;
logic RST;
logic input_grant;
logic [10:0] OUT;
logic clk;
initial begin
RST = 1;
#5;
RST = 0;
clk = 1;
#20;
RST = 1;
forever #50 clk = ~clk;
end
initial begin
D = 'h1;
repeat(3) @(posedge clk);
D = 'h2;
repeat(10) @(posedge clk);
D = 'hA;
repeat(10) @(posedge clk);
$finish;
end
multi_sel u0_multi_sel (
.d(D),
.clk(clk),
.rst(RST),
.input_grant(input_grant),
.out(OUT)
);
initial begin
$fsdbDumpfile("tb_top.fsdb");
$fsdbDumpvars(0, tb_top);
end
endmodule
makefile脚本实现:
在命令行输入g Makefile
akefile
#// Creator: xiaobaijiang
#// time: 2022-04-21
#// wchat: jianfuk
#//-----------------------------------------------------------
run:
vcs -R -full64 +v2k -fsdb -sverilog multi.v multi_tb.sv -l run.log
verdi:
verdi -sv multi.v multi_tb.sv -ssf tb_top.fsdb &
clean:
@rm -rf verdiLog *.log *.fsdb csrc ucli.key simv* *.conf *.rc
仿真看波形:
在命令行输入make run
,如下图:
然后在命令行输入make verdi
更多芯片验证自学教程,请访问->传送门