[转帖]Verilog的语法及generate使用

verilog 单独文件调用 include 来源:http://www.cnblogs.com/surpassal/archive/2012/05/31/2527931.html Verilog中可以使用预处理命令 `include "文件名" 来包含新文件。
`include "文件名"的位置需要在 module声明之后。
这里举个例子,param.h存放了参数LENTH,顶层mult.v使用了它。
mult.v代码如下

1 module mult ( 2 input clk, 3 input rst, 4 input [LENTH-1:0] A, 5 input [LENTH-1:0] B, 6 output [LENTH-1:0] C 7 ); 8 9 `include "param.h" 10 11 reg [LENTH-1:0] c_reg; 12 13 always@(posedge clk or negedge rst) 14 if(rst == 1'b0)begin 15c_reg <= 32'b0; 16 end 17 else begin 18c_reg <= A*B; 19 end 20 21 assign C = c_reg; 22 23 endmodule

aram.h代码如下

parameter LENTH = 32;





2014-04-1015:39:17周四 来源:http://www.eefocus.com/zhaochengshun/blog/13-12/300789_21a6e.html verilog 条件编译命令`ifdef、`else、`endif 的应用(经常用于主程序中添加测试信息。。。) 通常在Verilog HDL程序中用到`ifdef、`else、`endif编译命令的情况有以下几种:
?选择一个模块的不同代表部分。
?选择不同的时序或结构信息。
?对不同的EDA工具,选择不同的激励。 [转帖]Verilog的语法及generate使用
文章图片
[转帖]Verilog的语法及generate使用
文章图片
1 module ifdef_test(out); 2 output out; 3 `define wow 4 `define nest_one 5 `define second_nest 6 `define nest_two 7 `ifdef wow 8initial $display("wow is defined"); 9`ifdef nest_one 10initial $display("nest_one is defined"); 11`ifdef nest_two 12initial $display("nest_two is defined"); 13`else 14initial $display("nest_two is not defined"); 15`endif 16`else 17initial $display("nest_one is not defined"); 18`endif 19 `else 20initial $display("wow is not defined"); 21`ifdef second_nest 22initial $display("second_nest is defined"); 23`else 24initial $display("second_nest is not defined"); 25`endif 26 `endif 27 endmodule

View Code
1 module ifdef_test(out); 2 output out; 3 `define wow 4 `define nest_one 5 `define second_nest 6 `define nest_two 7 `ifdef wow 8initial $display("wow is defined"); 9`ifdef nest_one 10initial $display("nest_one is defined"); 11`ifdef nest_two 12initial $display("nest_two is defined"); 13`else 14initial $display("nest_two is not defined"); 15`endif 16`else 17initial $display("nest_one is not defined"); 18`endif 19 `else 20initial $display("wow is not defined"); 21`ifdef second_nest 22initial $display("second_nest is defined"); 23`else 24initial $display("second_nest is not defined"); 25`endif 26 `endif 27 endmodule


[转帖]Verilog的语法及generate使用
文章图片
运行结果为: # wow is defined
# nest_one is defined
# nest_two is defined
2013-06-2808:32:40 周五 1、常量(constant)、参数(parameter)、块标号(block label)最好使用大写命名,变量(variable)、实例(instance)、结构 代码1.1 模-m计数器(缺省为模-10计数器)
module mod_m_bin_counter #(parameter M=10) // mod-M ( // global clock and asyn reset input clk, input rst_n, // counter interface output max_tick, output min_tick, output [N-1:0] q ); // signal declaration localparam N = log2(M); // number of bits in counter reg [N-1:0] r_reg; wire [N-1:0] r_next; // body // register always@(posedge clk, negedge rst_n) if(!rst_n) r_reg <= 0; else r_reg <= r_next; // next-state logic assign r_next = (r_reg == (M-1)) ? 0 : r_reg + 1'b1; //output logic assign q = r_reg; assign max_tick = (r_reg == (M-1)) ? 1'b1 : 1'b0; // log2 constant function function integer log2(input integer n); integer i; begin log2 = 1; for(i=0; 2**i
根据这个模-m计数器,我们再写一个testbench。
使用动态索引的Verilog代码即用可变的索引或地址作为位选择或存储器元素 循环语句或算术运算符因为这些代码要被合并成大量难以优化的门。jitter抖动,skew倾斜。flip-flop触发器-边沿敏感,latch锁存器-电平敏感。阻塞赋值-值立即更新,含连续赋值和过程赋值。 offset补偿,preset预置。 1、可变索引位选择描述的 多路开关。 module BitSelect2(Din, BitSel, Dout); input [3:0] Din; input [1:0] BitSel; output Dout; reg Dout; always @(Din or BitSel) Dout = Din[BitSel]; endmodule 2、可变索引位选择实现 译码器。 module BitSelectDecoder(Din, BitSel, Dout); input Din; input [1:0] BitSel; output [3:0]Dout; reg [3:0]Dout; always @(Din or BitSel) Dout[BitSel] = Din; endmodule 3、条件表达式的综合:assign Dout = (c1^c2) ? Din : 0; 4、always语句的综合 always语句中定义的变量都是临时变量。 对于纯组合逻辑,always语句中要使用完整的事件列表,而临时变量不需要列入。 5、if语句、case语句要采用完整的分支语句,否则会产生锁存器(电平敏感)。赋初值避免综合出锁存器。 用default分支语句避免综合出锁存器。使用"full_case"指令避免综合出锁存器。使用"parallel_case"指令避免综合出锁存器。 并行的case语句: module parallelCase(key,decoder); input [3:0] key; output [1:0] decoder; reg [1:0] decoder; always @(key) casex(key) //synthesis parallel_case 4'bxxx1: decoder = 0; //等价的if语句:if(key[0])decoder = 0; 4'bxx1x: decoder = 1; //if(key[1])decoder = 1; 4'bx1xx: decoder = 2; //if(key[2])decoder = 2; 4'b1xxx: decoder = 3; //if(key[3])decoder = 3; endcase endmodule//若不用 //synthesis parallel_case就会综合出优先级解码器。 将"full_case"综合指令用于条件表达式使用常量的case语句。 module parallelCase(key,decoder); input [3:0] key; output [1:0] decoder; reg [1:0] decoder; always @(key) casex(1) //synthesis full_case key[0]: decoder = 0; key[1]: decoder = 1; key[2]: decoder = 2; key[3]: decoder = 3; endcase endmodule //我想到的方法,用for循环。 module parallelCase(key,decoder); input [3:0] key; output [1:0] decoder; reg [1:0] decoder; always @(key) begin: LOOP1 integret i; decoder = 0; for(i=0,i<4,i=i+1) if(key[i]) decoder = i; else decoder = decoder; end endmodule 6、利用任务实现串行移位乘法器 module TaskMultiplier(clk, a, b, c) input clk; input [3:0] a, b; output [7:0] c; reg [7:0] c; always @(posedge clk) begin multiply(a,b,c); end task multiply; input [3:0] a, b; output [7:0] c; begin: serialMult reg [3:0] tempa; reg [7:0] tempb, tempc; tempa = a; tempb = {4'b0, b}; tempc = 0; repeat(4) begin//推荐使用,GOOD! if(tempa[0]) tempc = tempc+tempb; tempa = tempa>>1; tempb = tempb<<1; end c = tempc; end endtask 或者用另外一种方法实现task功能,采用for语句 静态循环描述的无符号乘法器。 task multiply; input [3:0] a, b; output [7:0] c; begin: serialMult integret i; reg [7:0] tempb, tempc; tempb = {4'b0, b}; tempc = 0; //赋初值避免综合成锁存器。 for(i=0; i<4; i=i+1) begin //不推荐 if(a[i]) tempc = tempc+tempb; tempb = tempb<<1; end c = tempc; end endtask 或者用优化的CODE,用while语句非静态循环描述无符号乘法器。非静态循环是指循环的次数是由运算中的某个变量决定,而不是编译器确定。但有的EDA不支持非静态循环。如QuartusII。好处是一旦a中的高位全为0,则整个乘法去处结束。这在数据字较长时有明显的效果。 task multiply; input [3:0] a, b; output [7:0] c; begin: serialMult reg [3:0] tempa; reg [7:0] tempb, tempc; reg [3:0] shift_cnt; tempa = a; tempb = {4'b0, b}; tempc = 0; shift_cnt = 0; //calc the number of 1 in the tempa. while(|tempa) begin//推荐使用,GOOD!if(tempa[0]) tempc = tempc+tempb; tempa = tempa>>1; tempb = tempb<<1; shift_cnt = shift_cnt + 1; end c = tempc; end endtask endmodule 来源: http://bbs.ednchina.com/BLOG_ARTICLE_3003610.HTM 虎虎小猪
verilog之generate的使用 发布时间:2012-05-03 16:10:03
技术类别:CPLD/FPGA
Verilog-2001添加了generate循环,允许产生module和primitive的多个实例化,同时也可以产生多个variable,net,tash,function,continous assignment ,initial和always。在generate语句中可以引入if-else和case语句,根据条件不同产生不同的实例。
为此,verilog-2001增加了以下关键字:generate, endgenerate, genvar, localparam。genvar为新增的数据类型,存储正的integer。在generate语句中使用的index必须定义成genvar类型。localparam与parameter有些类似,不过其不能通过redefinition改变值。除了可以在generate语句使用if-else,case外,还能使用for语句进行循环。
实例1.generate-for循环:例化8-bit加法器
generate
genvar i;
for (i=0; i<=7; i=i+1)
begin : for_name
adder add (a[8*i+7 : 8*i], b[8*i+7 : 8*i], ci[i], sum_for[8*i+7 : 8*i], c0_or[i+1]);
end
endgenerate
for循环以begin开始,end结束,begin后边必须有一个唯一的标识符。
在for循环里使用always语句:
generate
genvar i;
//ant0
for (i = 0; i < 11; i = i + 1) begin : carrier_iq_data_gen
always @ (ul_a0_i_vld or ul_a0_q_vld) begin
ul_a0_iq[i * 2]= ul_a0_i_vld[i];
ul_a0_iq[i * 2 + 1] = ul_a0_q_vld[i];
end
endgenerate

实例2.generate-if-else例化不同的实例:基于数据宽度,例化乘法器
generate
if (IF_WIDTH < 10)
begin : if_name
multiplier_imp1 # (IF_WIDTH) u1 (a, b, sum_if);
end
else
begin : else_name
multiplier_imp2 # (IF_WIDTH) u2 (a, b, sum_if);
end
endgenerate

实例3.generate-case例化不同的实例:基于数据宽度,例化加法器
generate
case (WIDTH)
1:
begin : case1_name
adder #(WIDTH*8) x1 (a, b, ci, sum_case, c0_case);
end
2:
begin : case2_name
【[转帖]Verilog的语法及generate使用】adder #(WIDTH*4) x2 (a, b, ci, sum_case, c0_case);
end
default:
begin : d_case_name
adder x3 (a, b, ci, sum_case, c0_case);
end
endcase
endgenerate
2013-06-0313:52:21 周一 阴 coeff多项式系数 parameter DYNAMIC_PREC = 16; parameter DYNAMIC_LEVEL = 10; parameter DYNAMIC_COEFF_0 = 0 * (2**DYNAMIC_PREC-1) / DYNAMIC_LEVEL; //the calculation is 0 parameter DYNAMIC_COEFF_1 = 1 * (2**DYNAMIC_PREC-1) / DYNAMIC_LEVEL; //the calculation is 6553 2**DYNAMIC_PREC is 2^DYNAMIC_PREC // log2 constant function function integer log2( input integer n); integer i; begin log2 = 1; for (i=0; 2**i log2 = i + 1; end endfunction 2013-05-3109:51:10 周五 晴 来源: http://blog.163.com/liu_yi_xf/blog/static/13895064420122131092480/ Verilog中`include路径的设置在写Verilog的testbetch文件时,如果*.v文件中使用`include命令时,要特别的指名下路径,这是因为测试tb文件与代码rtl文件是在不同的目录下,只有指名调用路径才能跨目录仿真。例如:
project目录
---myproject(QuartusII 工程目录)
|
|---- comm// 要include的文件存放的目录,文件为default_setting.v
|
|---- src// 工程源代码(.v文件)存放目录
|
|---- sim(仿真工程目录)
按照上面的文档组织格式,如果src文件夹中的top.v文件中要include文件default_setting.v 则将下面的命令写入top.v文件
`include "../comm/default_setting.v”
如果上面的形式不行,可以再加一级试下,我就再加一级可以。
`include "../../comm/default_setting.v”
如果将所有的源码文件放在同一文件夹目录下,则可以直接使用`include "default_setting.v”命令,无需指定路径。
2012-11-12周一 晴 对于组合逻辑模式选择的写法可以有两种,一种是采用generate ifelse和 assign 语句实现的。另外一种是采用ifdefelse 和assign语句实现的。 对于时序逻辑可以采用case语句实现。 来源: http://hi.baidu.com/jadekung/item/371217c0fd6df37088ad9ec9 及 http://bbs.ednchina.com/BLOG_ARTICLE_3003610.HTM generate语句使用if-else,case外,还能使用for语句进行循环 语法
`ifdef MacroName
VerilogCode...
[`else
VerilogCode...]
`endif
规则
?如果宏的名字已经用了`define 定义,那么只编译 Verilog 代码的第一个块。
?如果没有定义宏的名字,而且出现`else 伪指令, 那么只编译第二个块。
?这些伪指令可以嵌套。
?不被编译的代码都应是有效的 Verilog 代码。
`define primitiveModel
module Test;
...
`ifdef primitiveModel
MyDesign_primitives UUT (...);
`else
MyDesign_RTL UUT (...);
`endif
endmodule
来源: http://wenku.baidu.com/view/ab60218002d276a200292e51.html verilog中generate的用法。 格雷码与二进制的相互转换 Verilog实现:来源 http://hi.baidu.com/hikyuu/item/297a050aa091cd026c9048aa 在红外线技术中使用的0.85或者0.95微米波段的谩射传输,它允许有两种速率:1M和2M速率,在1M速率上,采用的是格雷编码:它的编码原理是每四位一组,每个组被编码成一个16位的码字,任意两个相临位只有一个二进制数不同,它和奇偶校验码都属于可靠性编码.
格雷码(Gray code)是由贝尔实验室的Frank Gray在1940年提出,用于在PCM(Pusle Code Modulation)方法传送讯号时防止出错,并于1953年三月十七日取得美国专利。格雷码是一个数列集合,相邻两数间只有一个位元改变,为无权数码,且格雷码的顺序不是唯一的。
直接排列
以二进制为0值的格雷码为第零项,第一项改变最右边的位元,第二项改变右起第一个为1的位元的左边位元,第三、四项方法同第一、二项,如此反覆,即可排列出n个位元的格雷码。
二进制数转格雷码
(假设以二进制为0的值做为格雷码的0)
格雷码第n位 = 二进制码第(n+1)位+二进制码第n位。不必理会进制。Verilog 代码:gray=(binary>>1)^binary;
格雷码转二进制数
二进制码第n位 = 二进制码第(n+1)位+格雷码第n位。因为二进制码和格雷码皆有相同位数,所以二进制码可从最高位的左边位元取0,以进行计算。verilog 代码://------假设 reg [n-1] gray,binary; integer i; for(i=0; i<=n-1; i=i+1)binary[i]= ^(gray>>i)//gray移位后,自身按位异或^(gray>>i)//第一次看到这样的用法,特意查了下verilog语法 Verilog 的位运算语法:位逻辑运算符 在Verilog语言中有7种位逻辑运算符:
1~(非)
2&(与)
3|(或)
4^(异或)
5^~(同或)
6~&(与非)
7~|(或非)
位逻辑运算符对其自变量的每一位进行操作,例如,表达式A & B的结果是A和B的对应位相与的值。对具有不定值的位进行操作,视情况而定会得到不同的结果。例如:x和FALSE相与得结果x,x和TRUE相或得结果TURE。如果操作数的长度不相等,较短的操作数将用0来补位,逐位运算将返回一个与两个操作数中位宽较大的一个等宽的值。
在此需要注意的是,不要将逻辑运算符和位运算符相混淆,比如,!是逻辑非,而~是位操作的非,即按位取反,例如:对于前者!(5 = = 6)结果是TRUE,后者对位进行操作,~{1,0,1,1} = 0100。

一元约简运算符
约简运算符是单目运算符,也有与、或、非运算。其与、或、非运算规则类似于位运算符的与、或、非运算规则,但其运算过程不同。位运算是对操作数的相应位进行与、或、非运算,操作数是几位数则运算结果也是几位数。而约简运算则不同,约简运算是对单个操作数进行与、或、非递推运算,最后的运算结果是1位的二进制数。约简运算的具体运算过程是:1°先将操作数的第1位与第2位进行与、或、非运算;2°将运算结果与第3位进行与、或、非运算,依次类推,直至最后一位。
例如:
reg [3:0]B;
regC;
C = &B;
相当于:
C = ( (B[0]&B[1]) & B[2] ) & B[3];
一完整的模块举例如下:
module reduction(a, out1, out2, out3, out4, out5, out6);
input [3:0] a;
output out1, out2, out3, out4, out5, out6;
reg out1, out2, out3, out4, out5, out6;

always @ (a)
begin
out1 = & a; //与约简运算
out2 = | a; //或约简运算
out3 = ~& a; //与非约简运算
out4 = ~| a; //或非约简运算
out5 = ^ a; //异或约简运算
out6 = ~^ a; //同或约简运算
end

endmodule
一. 自然二进制码转换为二进制格雷码
原理:若二进制码表示为: B[N-1]B[N-2]...B[2]B[1]B[0]; 相应地, 则二进制格雷码表示为: G[N-1]G[N-2]...G[2]G[1]G[0].其中最高位保留: G[N-1] = B[N-1]; 其他各位: G[i] = B[i+1] xor B[i]. (i = 0, 1, 2, ..., n-2) Binary_to_Gray.v / Verilog module Binary_to_Gray (
input[N-1:0] B,
output reg[N-1:0] G
);

parameter N = N_bit_Binary; // 设置自然二进制码的位宽 integer i; always @ (B)
begin
G[N-1] = B[N-1];
for (i=0; iG[i] = B[i+1] ^ B[i];
end endmodule图2. N="4" 二. 二进制格雷码转换为自然二进制码
原理:若二进制格雷码表示为: G[N-1]G[N-2]...G[2]G[1]G[0]; 相应地, 则二进制码表示为: B[N-1]B[N-2]...B[2]B[1]B[0].其中最高位保留: B[N-1] = G[N-1]; 其他各位: B[i-1] = G[i-1] xor B[i]. (i = 1, 2, ..., n-1) Gray_to_Binary.v / Verilog module Gray_to_Binary (
input[N-1:0] G,
output reg[N-1:0] B
); parameter N = B_bit_Gray; // 设置二进制格雷码的位宽 integer i; always @ (G)
begin
B[N-1] = G[N-1];
for (i=1; i<=N-1; i="i"+1)
B[i-1] = G[i-1] ^ B[i];
end

endmodule 转载于:https://www.cnblogs.com/zlh840/archive/2012/09/26/2704221.html

    推荐阅读