提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
5.5、verilog
逻辑操作符如果一个操作数不为 0,它等价于逻辑 1;如果一个操作数等于 0,它等价于逻辑 0。
5.6、verilog
1.使用wire对reg赋值
如果reg型变量做赋值的左值,那么只有被驱动时才能接收到右值的赋值,具体方式可以使用always语句,将右值放入敏感列表中
//HDLBits-Vector3
module top_module (
input [4:0] a, b, c, d, e, f,
output [7:0] w, x, y, z );//
reg [31:0] m;
always@(a or b or c or d or e or f)//此处使用always语句进行对reg的赋值
begin
m<={a,b,c,d,e,f,2'b11};
end
assign z=m[7:0];
assign y=m[15:8];
assign x=m[23:16];
assign w=m[31:24];
endmodule
//除此之外也可以采用拼接的方式实现
module top_module (
input [4:0] a, b, c, d, e, f,
output [7:0] w, x, y, z );//
assign z={e[0],f,2'b11};
assign y={d[3:0],e[4:1]};
assign x={b[1:0],c,d[4]};
assign w={a,b[4:2]};
endmodule
2.使用拼接运算符
对于被拼接运算符拼接的内容,如果是重复变量或者重复常量的拼接需要加两层拼接运算符
HDLBits-Vector4
module top_module (
input [7:0] in,
output [31:0] out );//
assign out={{24{in[7]}},in};//in的拼接运算符可加可不加
endmodule
5.7 verilog
1.加法器
1.基本加法器
2.低延迟加法器
3.加减法器
sub为0,实现加法器功能
sub为1,实现减法器功能,异或门和1运算实现取反,在sub作为cin输入,取反加一为减法运算
2.模块例化
把端口(包括输入输出)作为研究对象,左侧为输入,可用reg或者wire,右侧为输出,因为要实时反应右侧的变化一定为wire
目前来看,如果仅要求右侧输出随左侧输入变化,在组合逻辑下使用reg作为右侧同样可行(吗)。
3.选择器
多选的选择器可以使用case语句
二选一为特殊情况,采取三元运算符简化
4.阻塞和非阻塞赋值
阻塞赋值为=,用于组合逻辑中,包括always@(*)
非阻塞赋值为<=,用于时序逻辑中,包括always@(possedge clk)
assign 赋值不用于always块中
5.8 verilog
1.case,casex和casez
case为全等比较,casez忽略z位,casex忽略z位和x位
2.归约操作符
归约操作符为单目运算符,对目标向量进行逐位运算
& a[3:0] // AND: a[3]&a[2]&a[1]&a[0].
5.9 MOLE
5.10
1.使用generate for实现实例化
//HDLBits-Adder100i
//for循环实例化100个1bit全加器
/*
1.generate例化可以使用对应的genvar变量
2.generate for语句要在begin后为循环实例命名
3.for循环中实例化可以使用相同的名字,实际上循环实例化后命名为
addloop[0] myadd,addloop[1] myadd...
*/
module top_module(
input [99:0] a, b,
input cin,
output [99:0] cout,
output [99:0] sum );
genvar i;
generate
for(i=0;i<100;i=i+1)
begin:addloop
if(i==0)
add myadd(.a(a[i]),.b(b[i]),.cin(cin),.sum(sum[i]),.cout(cout[i]));
else
add myadd(.a(a[i]),.b(b[i]),.cin(cout[i-1]),.sum(sum[i]),.cout(cout[i]));
end
endgenerate
endmodule
module add(input a,b,
input cin,
output sum,
output cout);
assign sum=a^b^cin;
assign cout=(a&b)|(a&cin)|(b&cin);
endmodule
2.向量之间比较
向量之间按位比较可以不使用for循环而是直接按位比较
HDLBits-Gatesv
module top_module (
input [3:0] in,
output [2:0] out_both,
output [3:1] out_any,
output [3:0] out_different
);
// Use bitwise operators and part-select to do the entire calculation in one line of code
// in[3:1] is this vector: in[3] in[2] in[1]
// in[2:0] is this vector: in[2] in[1] in[0]
// Bitwise-OR produces a 3 bit vector. | | |
// Assign this 3-bit result to out_any[3:1]: o_a[3] o_a[2] o_a[1]
// Thus, each output bit is the OR of the input bit and its neighbour to the right:
// e.g., out_any[1] = in[1] | in[0];
// Notice how this works even for long vectors.
assign out_any = in[3:1] | in[2:0];
assign out_both = in[2:0] & in[3:1];
// XOR 'in' with a vector that is 'in' rotated to the right by 1 position: {in[0], in[3:1]}
// The rotation is accomplished by using part selects[] and the concatenation operator{}.
assign out_different = in ^ {in[0], in[3:1]};
endmodule
3.三元运算符
三元运算符同样具有按位操作的能力,可以处理向量
4.十六进制表示
在使用十六进制表示时,如fff应该使用12’hfff而不是3’hfff表示
5.全1表示方法
reg [15:0] j;
j='1;
j=~0;
j=-1;//补码表示方法
5.11 MOLE
5.12 verilog
例化过程中尽量不要缺少输入输出变量
1,实现一个100bit加法器
//HDLBits-Adder100
module top_module(
input [99:0] a, b,
input cin,
output cout,
output [99:0] sum );
assign {cout,sum}=a+b+cin;
endmodule
首先,cin和a位数不同,不同位数的向量之间可以相加
其次,使用{cout,sum}将多个输出拼接为向量进行同时赋值
2.JK触发器
一种简明易懂的JK触发器verilog描述方法
//边沿JK触发器
module jk_trigger(clk, j, k, q);
input clk, j, k;
output q;
reg q;
wire qb;
always@(posedge clk) //时钟上升沿到来时,判断jk的值
begin
case({j,k})
2'b00: q <= q; //如果{j,k}=00,则触发器处于保持状态
2'b01: q <= 1'b0; //如果{j,k}=01,则触发器置1
2'b10: q <= 1'b1; //同理10,清零
2'b11: q <= ~q; //11,翻转
default: q <= q;
endcase
end
assign qb = ~q;
endmodule
我写的狗屎
module top_module (
input clk,
input j,
input k,
output Q);
always@(posedge clk)begin
Q<=(j^k)?j:(j?~Q:Q);
end
endmodule
5.13 verilog
5.14verilog
1.复位
能使用同步复位的情况尽量不不使用异步复位,以下代码若使用异步复位会因为某些原因出现错误
module top_module (
input clk,
input reset,
input [31:0] in,
output [31:0] out
);
reg [31:0] lastin;
always@(posedge clk)begin// 异步复位 always@(posedge clk,posedge reset)begin
if(reset)
out<=32'b0;
else
out<=~in&lastin|out;
lastin<=in;
end
endmodule
5.15 MOLE
5.16 verilog
1.关于模块输出
可以直接用赋值的方法控制模块输出
//Count15-HDLBits
//我的解法,兜了个圈子
module top_module (
input clk,
input reset, // Synchronous active-high reset
output [3:0] q);
reg [3:0]cnt;
always@(posedge clk)begin
if(reset)
cnt<=0;
else
cnt<=cnt+1;
end
assign q=cnt;
endmodule
//答案解法
module top_module(
input clk,
input reset,
output reg [3:0] q);
always @(posedge clk)
if (reset)
q <= 0;
else
q <= q+1; // Because q is 4 bits, it rolls over from 15 -> 0.
// If you want a counter that counts a range different from 0 to (2^n)-1,
// then you need to add another rule to reset q to 0 when roll-over should occur.
endmodule
2.复位
可以采用将多种复位条件使用||并列在同意条件语句中
module top_module(
input clk,
input reset,
output reg [3:0] q);
always @(posedge clk)
if (reset || q == 9) // 使用逻辑或
q <= 0;
else
q <= q+1;
endmodule
5.21 verilog
1.模块例化
模块例化的输入可以连接
1.topmodule的input
2.topmodule的output
3.直接填表达式
HDLbits-Exams/ece241 2014 q7a
module top_module (
input clk,
input reset,
input enable,
output [3:0] Q,
output c_enable,
output c_load,
output [3:0] c_d
); //
assign c_enable=enable;
assign c_load=reset|(Q==4'b1100&enable);
assign c_d=1;
wire myload;
count4 mycnt(.clk(clk),.enable(enable),.load(myload),.d(1),.Q(Q));
//这里load可以直接连c_load,c_load作为output直接连上端口虽然有点反直觉但是是可行的
//count4 mycnt(.clk(clk),.enable(enable),.load(reset|(Q==4'b1100&enable)),.d(1),.Q(Q)); 端口连接表达式
endmodule