当前位置:   article > 正文

Verilog基础知识_verilog output reg赋初值

verilog output reg赋初值

I/O端口类型:

input             wire

output           wire/reg型

verilog可综合语句 assign,always,其中initial 语句不建议用在可综合语句中。

关于时标:

`timescale 时间单位/时间精度

`timescale 1ns/1ps

#3  延时3ns,精度为1ps,递增时,可以递增0.1ns

如果 `timescale 1ns/1ns,精度为1ns,递增时只能按照1ns开始递增

变量类型:wire ,reg

wire 线型

reg 寄存器

在Verilog中,寄存器要用reg来声明,但是reg声明的变量不一定都是寄存器,有可能是锁存器,或者查找表。

查找表:可以理解为数电中的真值表

对于线型,用assign进行赋值即可。

对于寄存器,包含数据输入D端,时钟输入clk端,使能信号en(可无),数据输出Q端。其中,clk是指同步脉冲,一般是指外部晶振提供的方波时钟,占空比50%,即高低电平各占一个时钟周期的50%,1表示高电平,0表示低电平,高到低为下降沿,低到高为上升沿,一般都为上升沿有效时,触发寄存器(也可以下降沿触发,但是reg型必须在always块内进行编程);当时钟clk上升沿触发D端将数据传输至Q端,如果寄存器没有到达下一个沿,继续保持当前数据;当下一个沿到来时,再由D端传输新的数据至Q端。(不含使能情况,若含有使能,则需要在时钟有效后,使能有效,才进行数据的传输)

FPGA一般接收的是方波时钟,而非正弦波时钟。

RTL电路基本结构:组合逻辑 + 时序逻辑

RTL级描述的就是寄存器级的输出传输

阻塞赋值 = :属于立即发生

组合逻辑用,输出受限于输入信号最长延时路径,

非阻塞赋值 <=:时钟沿触发

时序逻辑用,输出受限于时钟沿的到来

在使用always时触发列表由posedge或negedge触发,使用非阻塞赋值

在使用assign时,用阻塞赋值

生成锁存器一般是电平触发   always @(*)

生成寄存器的一般是沿触发  always @(posedge clk)

在代码中进行数值定义时,如果不声明前面的位宽则默认为32bit,写代码时需要写明位宽和进制;如果数据表述为32位宽,但实际数值不足32位宽,则高位补0。

例如: 255 默认32bit

// reg [7:0]  cnt = 8'd255;  

// reg [3:0]  cnt = 255;    cnt 实际上等于 4'd15, 4hf,4'b1111

// reg [3:0]  cnt = 81;    cnt 实际上等于 4'b0001

//0~255 随机数生成方式    {$random}%256

// %表示求模运算,返回值是除以256后的余数

//always #10   a = {$random}%256;

赋值语句:

assign c1 = a & b; //c1   wire

always @(posedge clk) begin

c2 <= a & b;  //c2   reg

end

//敏感列表不全会生成latch,所以建议直接使用 * 代替所有敏感变量

always @(*)begin

c3 <= a & b; // c3    reg

end

时钟频率计算:

时钟周期 20ns = 50 Mhz = 1 / 20

时钟周期 10ns = 100 Mhz = 1/10

F = 1/T

1s=10^3 ms=10^6 us=10^9 ns

1GHz=1000MHz,1MHz=1000kHz,1kHz=1000Hz

1s=1000ms,1 ms=1000μs,1μs=1000ns

时钟频率

    时钟周期

1Hz      

 1s

1KHz   

1ms

1MHz   

1μs

1GHz   

1ns

定义接口时,output  reg          c2=1'b0, 可给寄存器赋初始值;但是线网不可进行赋初始值。

运算符:

% 求模运算

假设得到0~9之间的随机数:a = {$random}%10;

判断 a 是否在 10 ~ 20 之间写法:

错误写法:if(10<a<20)

正确写法:if(10 < a && a < 20)

逻辑运算符(&&、||、!):结果为 1 或者 0

按位运算符(&、|、~):每一位都进行运算

条件运算符((x)?x:x)

移位运算发:

>>右移; 高位补0

<<左移;低位补0

位拼接运算符:{};   例如:d <= {a,b,c};

位拼接实现循环左移:po_a <= {po_a[6:0],po_a[7]};

位拼接实现循环右移:po_a <= {po_a[0],po_a[7:1]};

移位运算应用于并串转换,SPI接口协议将协议以方波的形式传递出去(实际数据8bit,但SPI输出的数据是在一根线上,所以可以用移位寄存器将输入的8bit并行数据以串行方式以1bit输出方式串行输出)

条件判断语句:if…else     case…endcase

PS:

在编写always块时,if else 叠加不易过多,不然可能造成线路的延时过多。因为,每一个 if else 语句都会生成一个选择器,而每两级选择器之间会存在线路延时,当 if else 过多时,选择器链路总延时就会很长,从而影响电路时序,当时序出问题时,就算是功能仿真正确,下板后电路也是不正确的。

另外:在使用 if else 时需要注意优先级造成的影响。

使用case…endcase语句可生成多路选择器,无延时,并行判断,勿漏default(组合逻辑中),不然会生成 latch:

对于:

else if(cnt == 4'd15)

        cnt <= 4'd0;

如果cnt最大值是cnt位宽所能容纳的最大值时,计数到最大值后自动清零;

反之,如果位宽所能容纳的最大值不是cnt的最大值时,就需要加限制条件。

时钟分频:(在FPGA中,如果不调用PLL,则无法进行倍频)

在FPGA开发板上面只有一个晶振,即只有一种频率的时钟,如果需要用到不同频率的时钟,就需要在这个固定的时钟频率条件下进行分频或者倍频;

得到比固定的时钟频率更慢的时钟,进行分频操作;

得到比固定时钟频率更快的时钟,进行倍频操作;

时钟分频例子:呼吸灯

要求:从亮到灭的时间为 2s,从灭到亮的时间为 2 秒,完成呼吸的过程一共需要 4 秒时间。

解析:2s/1000份 = 2000000ms = 2000us,将2000us再分1000份=2us,

50Mhz=20ns,2us/20ns = 100,最小计数为100,计数1000次,得到一个2/1000 s,

计满1000个2/1000 s 即为2s,每2/1000 s 为1个PWM周期。

波形图:

  1. RTL code:
  2. module breathing_led(
  3. input wire clk,rst,
  4. output reg led
  5. );
  6. reg [6:0] clk50m_cnt;
  7. reg [9:0] clk50m_cnt_1000;
  8. reg [9:0] pwn_cnt_1000;
  9. reg pwn_flag;
  10. always @(posedge clk)begin
  11. if(rst)
  12. clk50m_cnt <= 7'd0;
  13. else if(clk50m_cnt == 7'd99)
  14. clk50m_cnt <= 7'd0;
  15. else
  16. clk50m_cnt <= clk50m_cnt + 1'b1;
  17. end
  18. always @(posedge clk)begin
  19. if(rst)
  20. clk50m_cnt_1000 <= 10'd0;
  21. else if(clk50m_cnt == 7'd99 && clk50m_cnt_1000 == 10'd999)
  22. clk50m_cnt_1000 <= 10'd0;
  23. else if(clk50m_cnt == 7'd99)
  24. clk50m_cnt_1000 <= clk50m_cnt_1000 + 1'b1;
  25. end
  26. always @(posedge clk)begin
  27. if(rst)
  28. pwn_cnt_1000 <= 10'd0;
  29. else if(clk50m_cnt == 7'd99 && clk50m_cnt_1000 == 10'd999 && pwn_cnt_1000 == 10'd999)
  30. pwn_cnt_1000 <= 10'd0;
  31. else if(clk50m_cnt == 7'd99 && clk50m_cnt_1000 == 10'd999)
  32. pwn_cnt_1000 <= pwn_cnt_1000 + 1'b1;
  33. end
  34. always @(posedge clk)begin
  35. if(rst)
  36. pwn_flag <= 1'b0;
  37. else if(clk50m_cnt == 8'd99 && clk50m_cnt_1000 == 10'd999 && pwn_cnt_1000 == 10'd999)
  38. pwn_flag <= ~pwn_flag;
  39. end
  40. assign led = (pwn_flag==1'b1)?((clk50m_cnt_1000 < pwn_cnt_1000)?1'b1:1'b0):((clk50m_cnt_1000 < pwn_cnt_1000)?1'b0:1'b1);
  41. endmodule
  1. TB:
  2. `timescale 1ns/1ns
  3. module tb_breathing_led;
  4. reg clk,rst;
  5. wire led;
  6. initial begin
  7. clk=0;
  8. rst=1;
  9. #100
  10. rst=0;
  11. end
  12. always #10 clk = ~clk;
  13. breathing_led inst_breathing_led (
  14. .clk(clk)
  15. , .rst(rst)
  16. , .led(led)
  17. );
  18. endmodule

 Top-down设计

Top-down 设计即自顶向下的设计

2502535898dc4b7e9e75c870b204f1d8.png

在模块例化时:

如果模块内部接口是输入,连接的接口类型可以是 wire/reg;

如果模块内部接口是输出,连接的接口类型可以是 wire;

有限状态机

一段式指的是在一个 always块内使用时序逻辑既描述状态的转移,同时也描述数据的输出;

二段式指一个always 块使用时序逻辑描述状态转移,另外一个 always 块使用时序逻辑描述数据输出;

三段式指使用三个 always 块,一个 always 模块采用时序逻辑描述状态转移,一个 always 块采用组合逻辑判断状态转移条件,描述状态转移规律,另一个 always 块描述状态输出(可以用组合电路输出,也可以时序电路输出)。

  1. //状态机模板
  2. module 模块名(
  3. 端口 1,
  4. 端口 2,
  5. ...
  6. 端口 N,
  7. );
  8. /时序逻辑描述的状态转移
  9. always@(posedge clk or negedge rst_n)
  10. 状态转移;
  11. //时序逻辑描述的数据输出
  12. always@(posedge clk or negedge rst_n)
  13. 数据输出;
  14. endmodule

 对于modelsim自动化仿真脚本的建立:

  1. run.tcl
  2. #退出仿真
  3. quit -sim
  4. #清除临时保存的仿真文件
  5. .main clear
  6. #建立库
  7. vlib work
  8. #编译 .v
  9. vlog ./tb_test.v
  10. #编译所有 .v 到work库中
  11. vlog ./../src/*.v
  12. #启动仿真,-voptargs+=acc(等于手动点simulation),选择work库中的tb顶层文件,进行仿真
  13. vsim -voptargs+=acc work.tb_test
  14. #添加wave
  15. add wave /tb_test/test_init/*
  16. #执行1us
  17. run 1us

状态机例子:

一个自动售货机中的商品 2.5 元一件,每次投币既能投入 1 元, 也能投入 0.5 元,当投入 3 元时,找零0.5元,使用状态机描述。

  1. RTL code
  2. modele fsm(
  3. input wire clk,
  4. input wire rst,
  5. input wire pi_money,
  6. output reg po_money,
  7. output reg po_water
  8. );
  9. reg [4:0] state;
  10. parameter idle = 5'b00001;
  11. parameter half = 5'b00010;
  12. parameter one = 5'b00100;
  13. parameter one_half = 5'b01000;
  14. parameter two = 5'b10000;
  15. always @(posedge clk)begin
  16. if(rst==1'b1)begin
  17. state <= idle;
  18. end
  19. else begin
  20. case(state)
  21. idle : if(pi_money == 1'b1) state <= one;
  22. else if(pi_money == 1'b0) state <= half;
  23. half : if(pi_money == 1'b1) state <=one_half;
  24. else if(pi_money == 1'b0) state <= one;
  25. one : if(pi_money == 1'b1) state <= two;
  26. else if(pi_money == 1'b0) state <= one_half;
  27. one_half: if(pi_money == 1'b1) state <= idle;
  28. else if(pi_money == 1'b0) state <= two;
  29. two : if(pi_money == 1'b1) state <= idle;
  30. else if(pi_money == 1'b0) state <= idle;
  31. default : state <= idle;
  32. endcase
  33. end
  34. end
  35. always @(posedge clk)begin
  36. if(rst==1'b1)begin
  37. po_water <= 1'b0;
  38. po_money <= 1'b0;
  39. end
  40. else if(state == one_half && pi_money == 1'b1) || (state == two && pi_money == 1'b0)begin
  41. po_water <= 1'b1;
  42. po_money <= 1'b0;
  43. end
  44. else if (state == two && pi_money == 1'b1) begin
  45. po_water <= 1'b1;
  46. po_money <= 1'b1;
  47. end
  48. end
  49. endmodule
  1. tb:
  2. `timescale 1ns/1ns
  3. module tb_fsm;
  4. reg clk,rst,pi_money;
  5. wire po_money,po_water;
  6. initial begin
  7. rst = 1;
  8. clk = 0;
  9. pi_money = 0;
  10. #100
  11. rst = 0;
  12. end
  13. always #10 clk = ~clk;
  14. always #20 pi_money = {$random};
  15. fsm fsm_inst(
  16. .clk(clk)
  17. ,.rst(rst)
  18. ,.pi_money(pi_money)
  19. ,.po_money(po_money)
  20. ,.po_water(po_water)
  21. );
  22. endmodule
  1. run.tcl:
  2. quit -sim
  3. .main clear
  4. vlib work
  5. vlog ./tb_fsm.v
  6. vlog ./../src/*.v
  7. vsim -voptargs+=acc work.tb_fsm
  8. #定义结构体进行匹配
  9. virtual type{
  10. {5'b00001 idle}
  11. {5'b00010 half}
  12. {5'b00100 one}
  13. {5'b01000 one_half}
  14. {5'b10000 two}
  15. }abc;
  16. #创建新信号,(abc)强制转换
  17. virt function{(abc)/tb_test/test_init/state}new_state
  18. add wave /tb_fsm/fsm_init/*
  19. run 1us
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/411086
推荐阅读
相关标签
  

闽ICP备14008679号