verilog语法进阶

学习记录

case中使用通配符

module case_test(
input [1:0]sel,
output reg [3:0]y	,
output reg [3:0]yx	,
output reg [3:0]yz
    );
always@(*)
begin
	case (sel)
		2'b00:      y = 1;
		2'b01:      y = 2;
		2'bx0:      y = 3;
		2'b1x:      y = 4;
		2'bz0:      y = 5;
		2'b1?:      y = 6;
		default :   y = 7;
	endcase

casez (sel)
    2'b00:      yz = 1;
    2'b01:      yz = 2;
    2'bx0:      yz = 3;
    2'b1x:      yz = 4;
    2'bz0:      yz = 5;
    2'b1?:      yz = 6;
    default:    yz = 7;
endcase

casex (sel)
    2'b00   :   yx = 1;
    2'b01   :   yx = 2;
    2'bx0   :   yx = 3;
    2'b1x   :   yx = 4;
    2'bz0   :   yx = 5;
    2'b1?   :   yx = 6;
    default :   yx = 7;
endcase
end
endmodule
module case_tsb();
    reg [1:0]sel;
    wire [3:0]y;
    wire [3:0]yx;
    wire [3:0]yz;

    initial
    begin
        sel     = 2'b00;
        #10 sel = 2'b01;
        #10 sel = 2'b10;
        #10 sel = 2'b11;
        #10 sel = 2'bxx;
        #10 sel = 2'bx0;
        #10 sel = 2'b0x;
        #10 sel = 2'b1z;
        #10 sel = 2'bz1;
        #10 sel = 2'bzz;
    end
    case_test inst1(
		.sel(sel),
		.y(y),
		.yx(yx),
		.yz(yz)
		);
endmodule

在这里插入图片描述

可以使用casez语句,但是只能用“?”
verilog语法——case、casex、casez

截断

6’hff 会被截断成 6’3f

vivado标志调试 ???

(* mark_debug = “true” *)reg [25:0] cnt ;

逻辑或与按位或

   assign out_or_bitwise = a | b;	
   assign out_or_logical = a || b;

注意向量隐式赋值 ,使用 `default_nettype none 避免bug???

wire [2:0] a, c;   // Two vectors
assign a = 3'b101;  // a = 101
assign b = a;       // b =   1  implicitly-created wire
assign c = b;       // c = 001  <-- bug
my_module i1 (d,e); // d and e are implicitly one-bit wide if not declared.
                    // This could be a bug if the port was intended to be a vector.

`default_nettype none避免verilog将未宣告的信号视为wire

创建内存

reg [7:0] mem [255:0];   // 256 unpacked elements, each of which is a 8-bit packed vector of reg.
reg mem2 [28:0];         // 29 unpacked elements, each of which is a 1-bit reg.

数组

数组定义

output reg [0:0] y;   // 1-bit reg that is also an output port (this is still a vector)
input wire [3:-2] z;  // 6-bit wire input (negative ranges are allowed)
wire [0:7] b;         // 8-bit wire where b[0] is the most-significant bit.
// writing vec[0:3] when vec is declared wire [3:0] vec is illegal
  • 学习千万不能学死,活学活用

数组元素切片

  w[3:0]      // Only the lower 4 bits of w
  x[1]        // The lowest bit of x  	reg [4:1] x;
  x[1:1]      // ...also the lowest bit of x	reg[4:1] x;
  z[-1:-2]    // Two lowest bits of z		wire [3:-2] z
  b[3:0]      // Illegal. Vector part-select must match the direction of the declaration. wire [0:7] b
  b[0:3]      // The *upper* 4 bits of b.	wire [0:7] b
  assign w[3:0] = b[0:3];    // Assign upper 4 bits of b to lower 4 bits of w. w[3]=b[0], w[2]=b[1], etc.

位拼接运算

示例

assign {w,x,y,z} = {a,b,b,c}; 
assign {o2, o1, o0} = vec;
assign {w, x, y, z} = {a, b, c, d, e, f, 2'b11};

数字拼接不合法

`{1, 2, 3}` is illegal and results in the error message: `unsized constants are not allowed in concatenations`.

进位写法的应用

        module top_module( 
            input [99:0] a, b,
            input cin,
            output cout,
            output [99:0] sum );
        
            assign {cout, sum} = a + b  + cin;
            
        endmodule        

8选1多位选择器

	// Create a 8-to-1 mux that chooses one of the bits of q based on the three-bit number {A,B,C}:
	// There are many other ways you could write a 8-to-1 mux
	// (e.g., combinational always block -> case statement with 8 cases).
	assign Z = q[ {A, B, C} ];

可以将拼接的结果作为索引

复制运算

{5{1'b1}}           // 5'b11111 (or 5'd31 or 5'h1f)
{2{a,b,c}}          // The same as {a,b,c,a,b,c}
{3'd5, {2{3'd6}}}   // 9'b101_110_110. It's a concatenation of 101 with
                    // the second vector, which is two copies of 3'b110.
module top_module (
    input [7:0] in,
    output [31:0] out );//

    // assign out = { replicate-sign-bit , the-input };
    //assign out = { 24{in[7]} , in };	
    //比较{24{in[7]}}与 24{in[7]},一个是向量,一个是一组数
    assign out = { {24{in[7]}} , in };

endmodule

区分高位有没有被赋值

  input [15:0] in;
  output [23:0] out;
  assign {out[7:0], out[15:8]} = in;         // Swap two bytes. Right side and left side are both 16-bit vectors.
  assign out[15:0] = {in[7:0], in[15:8]};    // This is the same thing.
  assign out = {in[7:0], in[15:8]};       
  // This is different. The 16-bit vector on the right is extended to match the 24-bit vector on the left, so out[23:16] are zero.
  // In the first two examples, out[23:16] are not assigned.

前两种方法高位没有赋值,最后一种方法,由于右侧补零,所以高位被赋值为0.

低位数与高位位数的逻辑运算

module top_module(
    input [31:0] a,
    input [31:0] b,
    input sub,
    output [31:0] sum
);
    wire [31:0]b1;
    assign b1 = b^{32{sub}};

endmodule 

{32{sub}}将sub补成32位,如果不补高位会补成0

例2

module top_module (
    input sel,
    input [7:0] a,
    input [7:0] b,
    output  [7:0]out  );

    // assign out = sel?a:b;
    
    // 1. A mux coded as (~sel & a) | (sel & b) does not work for vectors.
	// This is because these are bitwise operators, and sel is only a 1 bit wide quantity,
	// which leaves the upper bits of a and b zeroed. It is possible to code it using
	// the replication operator, but this is somewhat difficult to read:
    
    assign out = ( {8{~sel}} & a ) | ( {8{sel}} & b )
endmodule

向量逆向,注释没看懂???

module top_module (
	input [7:0] in,
	output [7:0] out
);
	
	assign {out[0],out[1],out[2],out[3],out[4],out[5],out[6],out[7]} = in;
	
	/*
	// I know you're dying to know how to use a loop to do this:

	// Create a combinational always block. This creates combinational logic that computes the same result
	// as sequential code. for-loops describe circuit *behaviour*, not *structure*, so they can only be used 
	// inside procedural blocks (e.g., always block).
	// The circuit created (wires and gates) does NOT do any iteration: It only produces the same result
	// AS IF the iteration occurred. In reality, a logic synthesizer will do the iteration at compile time to
	// figure out what circuit to produce. (In contrast, a Verilog simulator will execute the loop sequentially
	// during simulation.)
	always @(*) begin	
		for (int i=0; i<8; i++)	// int is a SystemVerilog type. Use integer for pure Verilog.
			out[i] = in[8-i-1];
	end


	// It is also possible to do this with a generate-for loop. Generate loops look like procedural for loops,
	// but are quite different in concept, and not easy to understand. Generate loops are used to make instantiations
	// of "things" (Unlike procedural loops, it doesn't describe actions). These "things" are assign statements,
	// module instantiations, net/variable declarations, and procedural blocks (things you can create when NOT inside 
	// a procedure). Generate loops (and genvars) are evaluated entirely at compile time. You can think of generate
	// blocks as a form of preprocessing to generate more code, which is then run though the logic synthesizer.
	// In the example below, the generate-for loop first creates 8 assign statements at compile time, which is then
	// synthesized.
	// Note that because of its intended usage (generating code at compile time), there are some restrictions
	// on how you use them. Examples: 1. Quartus requires a generate-for loop to have a named begin-end block
	// attached (in this example, named "my_block_name"). 2. Inside the loop body, genvars are read only.
	generate
		genvar i;
		for (i=0; i<8; i = i+1) begin: my_block_name
			assign out[i] = in[8-i-1];
		end
	endgenerate
	*/
	
endmodule

全加器

Full adder equations:
sum = a ^ b ^ cin
cout = a&b | a&cin | b&cin

不完整分支和不完整输出

每个if语句都应该加上else语句,防止出现锁存器

可以在always 开头给所有输出都提供默认值避免没有输出

逻辑X、Z

逻辑 X:表示未知,有可能是高电平,也有可能是低电平;(reg)
逻辑 Z:表示高阻态,外部没有激励信号是一个悬空状态。 (wire)

批量运算

    & a[3:0]     // AND: a[3]&a[2]&a[1]&a[0]. Equivalent to (a[3:0] == 4'hf)
    | b[3:0]     // OR:  b[3]|b[2]|b[1]|b[0]. Equivalent to (b[3:0] != 4'h0)
    ^ c[2:0]     // XOR: c[2]^c[1]^c[0]
    & a			//a中所有元素相或

You can also invert the outputs of these to create NAND, NOR, and XNOR gates, e.g., (~& d[7:0]).

同或与异或

同或

y = ~(a^b)	y = a ~^ b	
y  = (~a&~b) |(a&b)

异或

y = (a^b)
y = (~a&b)|(a&~b)

将变量所有位一起赋值

定义模块

module evaluate  #(parameter WIDTH = 16)
  ( input clk,
    input rst,
    input [WIDTH-1:0] din,
    output reg [WIDTH-1:0] dout
    );

  always @(posedge clk)
  begin
    if (rst)
      dout <= 'b0; //如何赋值
    else
      dout <= din;
    end
endmodule

全0

(1)直接赋0
dout <= 0;
此种情况下默认0为十进制以32位表示,如果din位宽大于32位,则高位补零,如果din位宽小于32位,则截取低位,仍为0。
(2)直接赋’b0
dout <= 'b0;
(3)利用位拼接
dout <= {WIDTH{1’b0}};
(4)supply0 ???
定义supply0 [WIDTH-1:0] dout_gnd,dout <= dout_gnd;

全1

(1)直接赋~0
dout <= ~0;
(2)直接赋-1
dout <= -1;
补数表示就是全1
(3)利用位拼接
dout <= {WIDTH{1’b1}};
(4)利用supply1
定义supply1 [WIDTH-1:0] dout_vcc dout <= dout_vcc;
需要注意的是Verilog中并没有’b1的赋全1方式。
out = '1; //好像不太合法

全X、全Z

赋全x或者全z均可采用’bx或者’bz的方式

结论

结论:赋全0、全x、全z可采用’b0、'bx或者’bz的方式;
赋全1可采用赋~0或赋-1的方式较为简洁。

参考.

一种写法

            module top_module( 
                input [1023:0] in,
                input [7:0] sel,
                output [3:0] out );
            assign out = in[sel * 4 +: 4];
            
                //second way	slice
                // Alternatively, "indexed vector part select" works better, but has an unfamiliar syntax:
            	// assign out = in[sel*4 +: 4];		// Select starting at index "sel*4", then select a total width of 4 bits with increasing (+:) index number.
            	// assign out = in[sel*4+3 -: 4];	// Select starting at index "sel*4+3", then select a total width of 4 bits with decreasing (-:) index number.
            	// Note: The width (4 in this case) must be constant.
                
            endmodule

这种写法是verilog 2001标准中新增加的,是向量部分选择的意思,如果sel等于0,in[sel * 4 +: 4]代表从0开始向上数4位,即in[3:0],建议大家学习使用这种方法,在sel位宽较大是可以有效减小工作量。

		// Note: The width (4 in this case) must be constant.
        assign out = in[sel*4 : sel*4+3];	

而上面的表述方法是错误的

当两个正数相加产生一个负数,或两个负数相加产生一个正数时,就会发生有符号溢出。有几种方法可以检测溢出:可以通过比较输入和输出数字的符号来计算溢出,或者从第n位和n-1位的进位得到溢出。

???

        	module top_module (
        		input [3:0] x,
        		input [3:0] y,
        		output [4:0] sum
        	);
        	// This circuit is a 4-bit ripple-carry adder with carry-out.
        	assign sum = x+y;	
        	// Verilog addition automatically produces the carry-out bit.Verilog加法自动产生携带位。
        	
        	// Verilog quirk: Even though the value of (x+y) includes the carry-out, (x+y) is still considered to be a 4-bit number (The max width of the two operands).
        	//即使(x+y)的值包含了进位,(x+y)仍然被认为是一个4位数字(两个操作数的最大宽度)
        	// This is correct:
        	// assign sum = (x+y);
        	// But this is incorrect:
        	// assign sum = {x+y};	// Concatenation operator: This discards the carry-out
        	//串联操作符:这将丢弃进位
        	endmodule

BCD编码

The BCD representation for the 5-digit decimal number 12345 is 20'h12345. This is not the same as 14'd12345 (which is 14'h3039).

The circuit is structured just like a binary ripple-carry adder, except the adders are base-10 rather than base-2.

5位十进制数字12345的BCD表示为20’h12345。这与14’d12345(它是14’h3039)不一样。

除了加法器是base-10而不是base-2之外,该电路的结构类似于二进制带波纹进位加法器。???


都看到这儿了,点个赞吧!

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值