当前位置:   article > 正文

Verilog基础模块_verilog module rom #( parameter

verilog module rom #( parameter

参数parameter:

        parameter可以用标识符定义常量,运用时只使用标识符即可,提高可读性及维护性。

        参数的传递:在一个模块中如果有定义参数,在其他模块调用此模块时可以传递参数,并可以修改参数,如下所示,在module后用#()表示。

  1. //定义的模块
  2. module rom #(
  3. parameter depth =16,
  4. parameter width = 8
  5. )
  6. (
  7. input [depth-1:0] addr ,
  8. input [width-1:0] data ,
  9. output result
  10. );
  11. endmodule
  12. //调用模块
  13. module top() ;
  14. wire [31:0] addr ;
  15. wire [15:0] data ;
  16. wire result ;
  17. rom
  18. #(
  19. .depth(32),
  20. .width(16)
  21. )
  22. rom rom_inst
  23. (
  24. .addr(addr) ,
  25. .data(data) ,
  26. .result(result)
  27. );
  28. endmodule

        Parameter可以用于模块间的参数传递,而localparam仅用于本模块内使用,不能用于参数传递,而Localparam多用于状态机状态的定义。

变量

wire

        Wire类型变量,也叫网络类型变量,用于结构实体之间的物理连接,,用连续赋值语句assign赋值。

Reg型

        Reg 类型变量,也称为寄存器变量,可用来储存值,必须在always语句里使用。也可以生成组合逻辑,,敏感信号没有时钟。

Memory型

        可以用memory类型来定义RAM,ROM等存储器,其结构为reg [n-1:0] 存储器名[m-1:0],意义为m个n位宽度的寄存器,m为存储器的深度,n为数据宽度。

赋值运算符

        “=”阻塞赋值,”<=”非阻塞赋值。阻塞赋值为执行完一条赋值语句,再执行下一条,可理解为顺序执行,而且赋值是立即执行;非阻塞赋值可理解为并行执行,不考虑顺序,在always块语句执行完成后,才进行赋值。

        一般情况下,在时序逻辑电路中使用非阻塞赋值,可避免仿真时出现竞争冒险现象;在组合逻辑中使用阻塞赋值,执行赋值语句后立即改变;在assign语句中必须用阻塞赋值。

        if (!a)表示条件为a的值不为1,也就是0。

拼接运算符

        “{ }”拼接运算符,将多个信号按位拼接,如{a[3:0], b[2:0]},将a的低4位,b的低3位拼接成7位数据。另外,{n{a[2:0]}}表示将n个a[2:0]拼接,{n{1’b0}}表示n位的0拼接。如{8{1’b0}}表示为8’b0000_0000。

带异步复位的D触发器

        异步复位是指独立于时钟,一旦异步复位信号有效,就触发复位操作,用于给信号复位,初始化。

  1. always @(posedge clk or negedge rst)
  2. begin
  3. if (rst == 1'b0)
  4. q <= 0 ;
  5. else
  6. q <= d;
  7. end

带异步复位同步清零的D触发器

        异步复位独立于时钟操作,而同步清零则是同步于时钟信号下操作的。不同于异步复位,同步操作不能把信号放到敏感列表里。

  1. always @(posedge clk or negedge rst)
  2. begin
  3. if (rst == 1'b0)
  4. q <= 0 ;
  5. else if (clr == 1'b1)
  6. q <= 0 ;
  7. else
  8. q <= d ;
  9. end

移位寄存器

  1. always @(posedge clk or negedge rst) begin
  2. if (rst == 1'b0)
  3. q <= 0 ;
  4. else
  5. q <= {q[6:0], d} ; //向左移位
  6. //q <= {d, q[7:1]} ; //向右移位
  7. end

单口RAM

单口RAM的写地址与读地址共用一个地址。

伪双口RAM

伪双口RAM的读写地址是独立的,可以随机选择写或读地址,同时进行读写操作。

真双口RAM

真双口RAM有两套控制线,数据线,允许两个系统对其进行读写操作。

单口ROM

ROM是用来存储数据的,可以按照代码形式初始化ROM,但这种方法处理大容量的ROM就比较麻烦,建议用FPGA自带的ROM IP核实现,并添加初始化文件。

有限状态机

        在verilog里经常会用到有限状态机,处理相对复杂的逻辑,设定好不同的状态,根据触发条件跳转到对应的状态,在不同的状态下做相应的处理。有限状态机主要用到always及case语句。

        Mealy有限状态机,输出不仅与当前状态有关,也与输入信号有关,在RTL中会与输入信号有连接。Moore有限状态机,输出只与当前状态有关,与输入信号无关,输入信号只影响状态的改变,不影响输出。

        采用一段式状态机的写法,只用一个always语句,所有的状态转移,判断状态转移条件,数据输出都在一个always语句里,缺点是如果状态太多,会使整段程序显的冗长。采用三段式状态机的写法,状态转移用一个always语句,判断状态转移条件是组合逻辑,采用一个always语句,数据输出也是单独的 always语句,这样写起来比较直观清晰,状态很多时也不会显得繁琐。

        采用Moore状态机三段式的写法设计一个8位的移位寄存器:

  1. module top(
  2. input shift_start,
  3. input shift_stop ,
  4. input rst ,
  5. input clk,
  6. input d,
  7. output reg [ 7:0] q
  8. );
  9. parameter Idle = 2'd0 ; // Idle state
  10. parameter Start = 2'dl ; // start state
  11. parameter Run = 2'd2 ; // Run state
  12. parameter Stop = 2'd3 ; // stop state
  13. reg [1:0] current_state ; // statement
  14. reg [1:0] next_state ;
  15. reg [4:0] delay_cnt ; // delay counter
  16. //First part: statement transition
  17. always @(posedge clk or negedge rst)begin
  18. if(!rst)
  19. current_state <= Idle ;
  20. else
  21. current_state <= next_state ;
  22. end
  23. //Second part: combination logic, judge statement transition condition
  24. always @(*)
  25. begin
  26. case (current _state)
  27. Idle: begin
  28. if(shift_start)
  29. next_state <=start ;
  30. else
  31. next_state <=Idle ;
  32. end
  33. start : begin
  34. if(delay cnt == 5'd99)
  35. next_state <=Run ;
  36. else
  37. next_state <=start ;
  38. end
  39. Run: begin
  40. if(shift_stop)
  41. next_state <=stop ;
  42. else
  43. next_state <=Run ;
  44. end
  45. stop:
  46. next_state <=Idle ;
  47. default:
  48. next_state <=Idle ;
  49. endcase
  50. end
  51. //Last part : output data
  52. always @ (posedge clk or negedge rst) begin
  53. if( !rst)
  54. delay_cnt <= 0 ;
  55. else if (current_state == Start)
  56. delay cnt <=delay cnt +1 'b1 ;
  57. else
  58. delay cnt <=0 ;
  59. end
  60. always @(posedge clk or negedge rst) begin
  61. if(!rst)
  62. q <= 0 ;
  63. else if( current_state == Run)
  64. q <={q[6:0], d};
  65. else
  66. q <=0;
  67. end
  68. endmodule

激励文件:

  1. `timescale 1 ns/1 ns
  2. module top_tb ();
  3. reg shift_start ;
  4. reg shift_stop ;
  5. reg rst ;
  6. reg clk:
  7. reg d ;
  8. wire [7:0]a ;
  9. initial
  10. begin
  11. rst = 0 :
  12. clk = 0 ;
  13. d = 0 ;
  14. #200 rst = 1 ;
  15. forever
  16. begin
  17. #( { $random} %100)//产生0~99的随机数
  18. d = ~d ;
  19. end
  20. end
  21. initial
  22. begin
  23. shift_start = 0 ;
  24. shift_stop = 0 ;
  25. #300 shift_start = 1 ;
  26. #1000 shift_start =0 ;
  27. shift_stop =1 ;
  28. #50 shift_stop = 0 ;
  29. end
  30. always #10 clk = ~clk ;
  31. top t0
  32. (
  33. .shift_start (shift_start) ,
  34. .shift_stop (shift_stop) ,
  35. .rst (rst) ,
  36. .clk (clk) ,
  37. .d (d) ,
  38. .q (q)
  39. ) ;
  40. endmodule

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/529111
推荐阅读
相关标签
  

闽ICP备14008679号