verilog自学小结

1 加法器电路

//add.v
module add(a, b, in, c, out);  
    input a;  
    input b;  
    input in;  
    output c;  
    output out;  
    assign {out, c} = a + b + in;  
endmodule  
//test_add.v
`timescale 1ns/1ns  
module count_t;  
    
  reg clk;  
  reg a;  
  reg b;  
  reg in;  
  wire c;  
  wire out; 
  add process(a, b, in, c, out);  
    
  initial  
      clk = 0;  
  always    
      forever  #5 clk = ~clk;  
  initial  
  begin  
        a = 0; b = 0; in = 0;  
        #10  a = 0; b = 0; in = 1;  
        #10  a = 0; b = 1; in = 0;  
        #10  a = 0; b = 1; in = 1;  
        #10  a = 1; b = 0; in = 0;  
        #10  a = 1; b = 0; in = 1;  
        #10  a = 1; b = 1; in = 0;  
        #10  a = 1; b = 1; in = 1;   
 end        
  //initial  
  //$monitor(" out = %d, c = %d\n", out, c);//监视函数     
endmodule  

总结1

数据类型wire与reg的区别:reg和wire类似于C、C++的变量,
wire相当于电路中的导线,对应于连续赋值,如assign,属于组合电路;
reg相当于电路中的寄存器,对应于过程赋值,只能在always,initial语块中用等号赋值,属于时序电路。

执行顺序:Verilog中,每行语句都是并发执行的,而在always,initial语块中,语句是顺序执行的,可以使用if等判断语句。

$monitor提供了监控输出列表中的表达式或变量值的功能,当参数列表中变量或者表达式的值发生变化是,整个参数列表中变量或者表达式的值都将输出显示。

timescale是Verilog HDL 中的一种时间尺度预编译指令,它用来定义模块的仿真的时间单位和时间精度。格式如下:
`timescale 仿真时间单位/时间精度

注意:
1)时间精度就是模块仿真时间和延时的精确程序,比如:定义时间精度为10ns,那么时序中所有的延时至多能精确到10ns,而8ns或者18ns是不可能做到的。
2)用于说明仿真时间单位和时间精度的 数字只能是1、10、100,不能为其它的数字。
3)时间精度不能比时间单位还要大。最多两则一样大。

比如:
下面定义都是对的:
`timescale 1ns/1ps
`timescale 100ns/100ns
而下面的定义是错的:
`timescale 1ps/1ns

2 8 bits counter with async clear and sync load

//counter8.v
module counter8 (clk,aclr,load,load_din,dout);
input clk;
input aclr;
input load;
input [7:0] load_din;
output [7:0] dout;
//InternalVariables
wire  clk ;
wire  aclr;
wire  load;
wire [7:0]load_din;
wire [7:0]dout;
reg  [7:0]counter = 0;
//CodeStarts Here
always @(posedge clk or negedge aclr)
	if(!aclr) counter <= 0;
	else if(load == 1)
          counter <= load_din;
	else counter <= counter + 1;
assign dout = counter;
endmodule
//test_counter8.v
`timescale 1ns/1ns                                  
module test_counter8;
reg clk;
reg aclr;
reg load;
reg [7:0] load_din;
wire [7:0] dout;
counter8 u(
          .clk(clk),
          .aclr(aclr),
          .load(load),
          .load_din(load_din),
          .dout(dout));
initial
begin
clk = 0;
aclr = 1;
load = 0;
load_din = 0;

#40             aclr = 1;
#20             load = 1;
          load_din = 100;
#20             load = 0;
#53 aclr = 0;
end
always #10 clk = ~clk;
endmodule

![波形图](file:///C:/Users/Administrator/Desktop/algorithms/wave1.png)

总结2

非阻塞(Non_Blocking)赋值方式( 如 b <= a; ),块结束后才完成赋值操作,值并不是立刻就改变的,这是一种比较常用的赋值方法。(特别在编写可综合模块时)。

阻塞(Blocking)赋值方式( 如 b = a; ),赋值语句执行完后,块才结束,值在赋值语句执行完后立刻就改变的, 可能会产生意想不到的结果。

一般情况下组合逻辑使用=赋值,时序逻辑使用<=赋值。
#40时间都是累加的

3 16*16FIFO

//fifo.v
module fifo(clock,reset,read,write,fifo_in,fifo_out,fifo_empty,fifo_half,fifo_full);
  input clock,reset,read,write;
  input [15:0]fifo_in;
  output[15:0]fifo_out;
  output fifo_empty,fifo_half,fifo_full;//标志位
  reg [15:0]fifo_out;
  reg [15:0]ram[15:0];
  reg [3:0]read_ptr,write_ptr,counter;//指针与计数
  wire fifo_empty,fifo_half,fifo_full;

  initial
	begin
	counter=0;
	read_ptr=0;
	write_ptr=0;
	end
  
  
  always@(*)
  if(reset)
    begin
    read_ptr=0;
    write_ptr=0;
    counter=0;
    fifo_out=0;                    //初始值
    end
  else
    case({read,write})
      2'b00:
            counter=counter;        //没有读写指令
      2'b01:                            //写指令,数据输入fifo
            begin
            ram[write_ptr]=fifo_in;
            counter=counter+1;
            write_ptr=(write_ptr==15)?0:write_ptr+1;
            end
      2'b10:                          //读指令,数据读出fifo
            begin
            fifo_out=ram[read_ptr];
            counter=counter-1;
            read_ptr=(read_ptr==15)?0:read_ptr+1;
            end
      2'b11:                        //读写指令同时,数据可以直接输出
            begin
            if(counter==0)
				fifo_out=fifo_in;
            else
                begin
                ram[write_ptr]=fifo_in;
                fifo_out=ram[read_ptr];
                write_ptr=(write_ptr==15)?0:write_ptr+1;
                read_ptr=(read_ptr==15)?0:write_ptr+1;
                end
            end
        endcase
		
    assign fifo_empty=(counter==0)?1:0;    //标志位赋值 组合电路
    assign fifo_half=(counter==8)?1:0;
    assign fifo_full=(counter==15)?1:0;
    endmodule
//test_fifo.v
`timescale 1ns/1ns
module test_fifo;
	reg clock;
	reg reset;
	reg read;
	reg write;
	reg [15:0]fifo_in;
	wire [15:0]fifo_out;
	wire fifo_empty;
	wire fifo_half;
	wire fifo_full;
	fifo process(clock,reset,read,write,fifo_in,fifo_out,fifo_empty,fifo_half,fifo_full);
	
	initial
	begin
		read=0;
		write=0;
		clock=0;
		reset=0;
		fifo_in=0;
	end
	
	always
		#4 clock=~clock;
 
	always
		#10 write=~write;
	always
		#20 read=~read;
	always
		#5 fifo_in=fifo_in+1;
endmodule

仿真结果

总结3

最开始仿真的时候输出总为x,重新检查了代码之后明白了是fifo内部变量没有赋初值,增加initial即可

猜你喜欢

转载自blog.csdn.net/tiaozhanzhe1900/article/details/82983158