Verilog/数电 知识点随记(1)

一、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

Verilog/数电 知识点随记(1)_第1张图片

2、generate/for(可综合)

  • generate用于和 for/if/casealways块外 选择/批量 生成电路

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 结果为 0110

2、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.5

4、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} XX: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

微信公众号:通信随笔XIDIAN

在这里插入图片描述

你可能感兴趣的:(verilog,verilog)