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
15 c_reg <= 32'b0;
16 end
17 else begin
18 c_reg <= A*B;
19 end
20
21 assign C = c_reg;
22
23 endmodule
aram.h代码如下
2014-04-10 15:39:17周四
来源:http://www.eefocus.com/zhaochengshun/blog/13-12/300789_21a6e.html
verilog 条件编译命令`ifdef、`else、`endif 的应用(经常用于主程序中添加测试信息。。。)
通常在Verilog HDL程序中用到`ifdef、`else、`endif编译命令的情况有以下几种:
• 选择一个模块的不同代表部分。
• 选择不同的时序或结构信息。
• 对不同的EDA工具,选择不同的激励。
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
8 initial $display("wow is defined");
9 `ifdef nest_one
10 initial $display("nest_one is defined");
11 `ifdef nest_two
12 initial $display("nest_two is defined");
13 `else
14 initial $display("nest_two is not defined");
15 `endif
16 `else
17 initial $display("nest_one is not defined");
18 `endif
19 `else
20 initial $display("wow is not defined");
21 `ifdef second_nest
22 initial $display("second_nest is defined");
23 `else
24 initial $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
8 initial $display("wow is defined");
9 `ifdef nest_one
10 initial $display("nest_one is defined");
11 `ifdef nest_two
12 initial $display("nest_two is defined");
13 `else
14 initial $display("nest_two is not defined");
15 `endif
16 `else
17 initial $display("nest_one is not defined");
18 `endif
19 `else
20 initial $display("wow is not defined");
21 `ifdef second_nest
22 initial $display("second_nest is defined");
23 `else
24 initial $display("second_nest is not defined");
25 `endif
26 `endif
27 endmodule
运行结果为:
# wow is defined
# nest_one is defined
# nest_two is defined
2013-06-28 08: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**i1)
log2 = i + 1;
end
endfunction
endmodule
根据这个模-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
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-03 13: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-31 09: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 if else 和 assign 语句实现的。另外一种是采用ifdef else 和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;
reg C;
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; i
G[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