一、verilog语法
1、计数器(课本上的版本)
- 本来一直使用case版本,最近翻书看到的下面版本。
module counter(
input clk,
input rst,
output reg [2:0]Q
);
parameter M = 5;//循环计数长度为5
parameter MM = M - 1;
wire Id;
assign Id = Q >= MM;
always @(posedge clk)begin
if(!rst)
Q <= 1'b0;
else
Q <= Id ? 1'b0 : Q+1'b1;
end
endmodule
2、generate/for(可综合)
- generate用于和 for/if/case 在 always块外 选择/批量 生成电路
generate-for
用法:
(1) 必须有genvar关键字定义for语句的变量。
(2)for语句的内容必须加begin和end(即使就一句)。
(3)for语句必须有个名字。
参看:verilog中generate语句的用法generate-if/case
选择性生成电路
参看:基础项目(7)generate语句块的讲解
-
for 循环单独用在always块内可以将需要重复编写的代码简化
-
可以使用 interger 做for循环判断变量(可综合)
例:使用pipeline方式将输入数据与本地数据相乘相乘并求和(为简化例子改为只求和)
`timescale 1ns / 1ps
module test_sum(
input clk,
input rst,
input [9:0]data_real,
input [9:0]data_imag,
input data_valid,
output reg [13:0]dout_real,
output reg [13:0]dout_imag,
output reg dout_valid
);
integer i,j,k,l,h,m,n;
reg [9:0]data_temp_real[7:0];//数据缓存 8->8
reg [9:0]data_temp_imag[7:0];
reg [10:0]data_temp_real_1[7:0];// 8->8
reg [10:0]data_temp_imag_1[7:0];
reg [11:0]data_temp_real_2[3:0];// 8->4
reg [11:0]data_temp_imag_2[3:0];
reg [12:0]data_temp_real_3[1:0];// 4->2
reg [12:0]data_temp_imag_3[1:0];
reg [4:0]int;
always @(posedge clk or negedge rst)begin
if(!rst)begin//复位并赋初值
int <= 5'b0;
for(i=0;i<=7;i=i+1)begin
data_temp_real[i] <= 10'b0;
data_temp_imag[i] <= 10'b0;
data_temp_real_1[i] <= 11'b0;
data_temp_imag_1[i] <= 11'b0;
end
for(j=0;j<=3;j=j+1)begin
data_temp_real_2[j] <= 12'b0;
data_temp_imag_2[j] <= 12'b0;
end
for(k=0;k<=1;k=k+1)begin
data_temp_real_3[k] <= 13'b0;
data_temp_imag_3[k] <= 13'b0;
end
dout_real <= 14'b0;
dout_imag <= 14'b0;
dout_valid <= 1'b0;
end else if(data_valid)begin//输出产生
case (int)
5'd11:begin dout_valid <= 1'b1;
int <= int;
end
default: int <= int + 1'b1;
endcase
for(l=0;l<=6;l=l+1)begin
data_temp_real[l+1] <= data_temp_real[l];//数据地址搬移
data_temp_imag[l+1] <= data_temp_imag[l];
end
data_temp_real[0] <= data_real;//数据输入
data_temp_imag[0] <= data_imag;
for(h=0;h<=7;h=h+1)begin
data_temp_real_1[h] <= data_temp_real[h]; //+ data_temp_imag[h]; //当前未设置共轭运算
data_temp_imag_1[h] <= data_temp_imag[h]; //- data_temp_imag[h];
end
for(m=0;m<=6;m=m+2)begin
data_temp_real_2[m/2] <= data_temp_real_1[m] + data_temp_real_1[m+1];//求和 8->4
data_temp_imag_2[m/2] <= data_temp_imag_1[m] + data_temp_imag_1[m+1];
end
for(n=0;n<=2;n=n+2)begin
data_temp_real_3[n/2] <= data_temp_real_2[n] + data_temp_real_2[n+1];//求和 4->2
data_temp_imag_3[n/2] <= data_temp_imag_2[n] + data_temp_imag_2[n+1];
end
dout_real <= data_temp_real_3[0] + data_temp_real_3[1];//求和 2->1
dout_imag <= data_temp_imag_3[0] + data_temp_imag_3[1];
end else begin//输入结束后剩余数据延迟输出
if(int > 0)
case (int)
5'd7:begin dout_valid <= 1'b0;
int <= 5'd0;
end
default: int <= int - 1'b1;
endcase
else int <= int;
if(int >= 8)begin
for(h=0;h<=7;h=h+1)begin
data_temp_real_1[h] <= data_temp_real[h]; //+ data_temp_imag[h];
data_temp_imag_1[h] <= data_temp_imag[h]; //- data_temp_imag[h];
end
for(m=0;m<=6;m=m+2)begin
data_temp_real_2[m/2] <= data_temp_real_1[m] + data_temp_real_1[m+1];
data_temp_imag_2[m/2] <= data_temp_imag_1[m] + data_temp_imag_1[m+1];
end
for(n=0;n<=2;n=n+2)begin
data_temp_real_3[n/2] <= data_temp_real_2[n] + data_temp_real_2[n+1];
data_temp_imag_3[n/2] <= data_temp_imag_2[n] + data_temp_imag_2[n+1];
end
dout_real <= data_temp_real_3[0] + data_temp_real_3[1];
dout_imag <= data_temp_imag_3[0] + data_temp_imag_3[1];
end
else begin//输出归零
dout_real <= 14'b0;
dout_imag <= 14'b0;
end
end
end
endmodule
3、verilog零散语法
1、 <<< / >>> 算数左移/右移
需要注意>>>作用于有符号数,左边会补符号位;<<<作用于有符号数,右边补0,符号位也被移走;
例:4’sb1011>>>1 结果为 1101,4’sb1011<<<1 结果为 01102、part-select (这里考虑左边为msb)即引用数组中一个元素的某几位
例:reg [9:0]a[9:0] 引用第0个元素的后四位:a[0][0+:4] 或 a[0][3-:4],其中 -:和+:左边可以是常数或者变量,右边必须是常数
3、表达式位长例1:a,b,c为16bit数,(a+b+17’b0)此中间量为17bit,c=(a+b+17’b0)>>1,可以正确保留进位
例2:testbench中延迟 25/2 结果为12,写为25/2.0结果为12.54、1’sb1表示 -1,1’sb0 表示 0
5、单纯的十进制数为 32bit interger 有符号数
6、±运算赋值运算 所有操作数是有符号数,那么结果才是有符号数。
二、数电知识点
1、竞争与冒险
- 内容
由于逻辑门存在延迟时间以及信号的传输路径不同,当输入信号电平发生瞬间变化时,电路可能产生与稳态时逻辑功能不一致的错误输出(冒险:毛刺)。
- 判别
X + X ‾ X +\overline{X} X+X:0形冒险(负向毛刺); X ⋅ X ‾ X\cdot\overline{X} X⋅X:1形冒险(正向毛刺)
K图存在相切,该处未被其他K圈包围。
- 冒险现象的消除
1、增加冗余项,消除逻辑冒险。(即在相切处加圈)
2、加滤波电路,消除毛刺的影响。
3、加选通信号,消除毛刺。
2、格雷(Gray)码记忆方法(异步FIFO地址跨时钟域交互)
1、1位:
0 1 \begin{matrix} 0\\ 1 \end{matrix} 01
2、2位(先竖着写出一位gray码,在下方将上方一位gray码倒写,再在上面两个数第二位补0,下面两个数第二位补1)
0 00 1 01 1 11 0 10 \begin{matrix} 0&00\\ 1&01\\ 1&11\\ 0&10 \end{matrix} 011000011110
3、依此法依次写出需要的gray码,如三位
00 000 01 001 11 011 10 010 10 110 11 111 01 101 00 100 \begin{matrix} 00&000\\ 01&001\\ 11&011\\ 10&010\\ 10&110\\ 11&111\\ 01&101\\ 00&100 \end{matrix} 0001111010110100000001011010110111101100