请阅读【嵌入式开发学习必备专栏 】
文章目录
- 移位运算与乘法
- Verilog Code
- verilog 拼接运算符({})
- Testbench Code
- VCS 波形仿真
- 问题小结
移位运算与乘法
已知d
为一个8
位数,请在每个时钟周期分别输出该数乘1/3/7/8,并输出一个信号通知此时刻输入的d有效(d给出的信号的上升沿表示写入有效)
可以看到输入D 的波形在为6的地方比较特殊,从波形上可以看到它只持续了一个时钟周期,但是out 在乘1/3/7/8的时候都是使用这个6,而且根本没有用到d上的128,下一个信号直接是129的4次运算。所以不能根据D的实时变化来计算out的实时变化。
所以在第一个input_grant的时候需要对输入信号进行寄存,寄存持续4个时钟周期都去改变它,直到下个有效数据到的时候再去寄存。乘法操作都是针对寄存下来的值进行。
input_grant 在执行乘1运算的时候拉高,这里采用计数器的方式,在复位的时候计数器归0,一旦复位失效拉成高电平之后就开始计数,计数值为0/1/2/3, 一共是2bits的信号, 根据计数值来判断输出,其实这种方式就是一个简化后的有限状态机的方式。
Verilog Code
module multi_sel(
input clk,
input rstn,
input[7:0] d,
output reg input_grant,
output reg[10:0] out
);
reg[1:0] count;
always @(posedge clk or negedge rstn) begin
if (~rstn) begin
count <= 2'b0;
end
else begin
count <= count + 1'b1;
end
end
// FSM methodology
reg[7:0] d_reg;
always@(posedge clk or negedge rstn) begin
if (~rstn) begin
out <= 11'b0;
input_grant <= 1'b0;
d_reg <= 8'b0;
end
else begin
case(count)
2'b00:begin
out <= d;
d_reg <= d;
input_grant <= 1'b1;
end
2'b01:begin
out <= d_reg + {d_reg, 1'b0}; // *3
input_grant <= 1'b0;
end
2'b10:begin
out <= d_reg + {d_reg, 1'b0} + {d_reg, 2'b0}; // *7
input_grant <= 1'b0;
end
2'b11:begin
out <= {d_reg, 3'b0}; // *8
input_grant <= 1'b0;
end
default: begin
out <= d;
input_grant <= 1'b0;
end
endcase
end
end
endmodule
verilog 拼接运算符({})
a = 2'b10;
b = 3'b101;
则:
c = {a, b} = 5'b10101;
d = {2'b00, a} = 4'b0010;
e = {3{a}} = 6'b101010;
f = {{2{a}, b 1'b1} = 8'b10101011;
拼接乘法
a = 4'b1110;
则
g = {a, 1'b0} = 5'b11100; // *2
Testbench Code
module test;
reg clk;
reg rstn;
reg[7:0] d;
reg input_grant;
reg[10:0] out;
multi_sel multi_sel_test(
.clk(clk),
.rstn(rstn),
.d(d),
.input_grant(input_grant),
.out(out)
);
initial begin
`ifdef DUMP_FSDB
$display("Dump fsdb wave!");
$fsdbDumpfile("test.fsdb");
$fsdbDumpvars;
`endif
end
initial begin
clk = 1'b0;
rstn = 1'b0;
d = 8'b0;
#15
rstn = 1'b1;
end
initial begin
repeat(200) begin
#10 clk =~clk;
$display("---run time ---: %d", $time);
if ($time >= 1000) begin
$finish;
end
end
end
initial begin
d = 8'd143;
#30 d = 8'd7;
#50 d = 8'd6;
#60 d = 8'd128;
#50 d = 8'd129;
#50 $finish;
end
endmodule
VCS 波形仿真
从波形图可以看到只有当input_grant
信号为高的时候 data 数据才有效,这里的input_grant
就类似于 AXI总线上的 valid 信号,用来表示数据是否有效。
问题小结
问题1
systemverilog 中输出信号赋值导致的error。
问题2 rstn 信号一直为0
检查 rstn 是否赋值为1’b1;