新闻  |   论坛  |   博客  |   在线研讨会
Verilog编写实战技巧(一)
0750long | 2010-03-10 21:14:02    阅读:3557   发布文章

Verilog编写实战技巧(一)

 

 

看了很多Altera官方的代码,总结了其中的一些比较好的编写形式和技巧,供大家参考。

信号写法

1.信号选通:

assign write_strobe = write & begintransfer;

 

2.使能信号是多个其他信号的逻辑与

assign control_reg_en = (address == 3'b001) && write && chipselect;

 

3.多级控制信号:三组信号,复合信号用粗体标注。

有些信号会在多处被使用,这样定义信号层次清晰。

assign write_strobe = write & begintransfer;

  assign stop_strobe_0 = (address == 0) && write_strobe;

  assign global_reset = stop_strobe_0 && writedata[0];

global_reset信号等效于下面:

assign global_reset =  (address == 0) &&(write & begintransfer )&& writedata[0];

 

4.表达式也可以给信号赋值

assign counter_is_zero = (internal_counter == 0);         

dma_mem_read_idle <= ((dma_mem_read_idle == 1) & (go == 0)) |

                    ((dma_mem_read_idle == 1) & (p1_done_read == 1)) ;

 

5.信号也可以是多个信号的组合。用{}实现

assign counter_load_value = {period_h_register,period_l_register};

 

6.寄存器的写选通可以通过片选、写信号和寄存器地址信号的逻辑与实现

assign status_wr_strobe = chipselect && ~write_n && (address == 0);

 

7. 将寄存器某几位作为控制信号定义出来,以便使用

  assign reen = control[5];

  assign ween = control[6];

assign leen = control[7];

 

8. 定义一个ram区域

         reg     [ 31: 0] mem_array [ 15: 0];

访问:mem_array[wraddress] <= data;

 

双向数据端口写法

 inout   [ 7: 0] LCD_data;

  assign LCD_data = (address[0]) ? 8'bz : writedata;

  assign readdata = LCD_data;

 

多路选择:

①assign read_mux_out = ({32 {(address == 0)}} & time_counter_0[31 : 0]) |

    ({32 {(address == 1)}} & time_counter_0[63 : 32]) |

    ({32 {(address == 2)}} & event_counter_0) |

    ({32 {(address == 4)}} & time_counter_1[31 : 0]) |

    ({32 {(address == 5)}} & time_counter_1[63 : 32]) |

    ({32 {(address == 6)}} & event_counter_1) |;

 

   ②assign control_readdata_temp = (slave_address == 3'b000)? status_register :

                                               (slave_address == 3'b001)? read_address_register :

                                               (slave_address == 3'b011)? length_register :

                                               (slave_address == 3'b110)? control_register :

                                               (slave_address == 3'b111)? checksum_register : 0;

 

从端口基本写

  always @(posedge clk or negedge reset_n)//always中赋值的变量为reg型,

    begin

      if (reset_n == 0)

          data_out <= 0;

      else if (chipselect && ~write_n && (address == 0))

          data_out <= writedata[15 : 0];

    end

assign out_port = data_out;//把reg型变量连续赋值给wire型变量

 

端口信号

//一个模块与多个其他模块有接口,端口分布时就按与其他模块连接分组,每一小组可以按先输入再输出排序。

module slave (

      // these connect to the clock port

      clk,

      reset,

      // these connect to the slave port

      slave_address,

      slave_read,

      slave_readdata,

      // these connect

      control_go,

      control_done,

      control_fixed_read_address,

      // this connects to the irq sender port

      control_irq

);

 

参数化调用

编写子模块时,尽量多用参数定义,使模块使用场合更灵活多变。

一般在模块端口定义后面紧跟着参数定义。

      parameter ADDRESSWIDTH = 32;

      parameter FIFODEPTH = 32;

      parameter FIFODEPTH_LOG2 = 5;

      localparam OFFSETWIDTH = LOG2(BYTEENABLEWIDTH);

上层模块在例化子模块时,可以对参数进行修改,在例化模块后用deparam

      latency_aware_read_master the_latency_aware_read_master (

             .clk (clk),

             .reset (reset),

             .control_fixed_location (fixed_read_address),  // RCON bit

             .control_read_base (read_address),

      );

      defparam the_latency_aware_read_master.ADDRESSWIDTH = 32;

      defparam the_latency_aware_read_master.FIFODEPTH = 32;

      defparam the_latency_aware_read_master.FIFODEPTH_LOG2 = 5;

 

寄存器写:

现有读选通信号,再在always中将读选通信号作为判断条件

  assign period_l_wr_strobe = chipselect && ~write_n && (address == 2);

  always @(posedge clk or negedge reset_n)

    begin

      if (reset_n == 0)

          period_l_register <= 849;

      else if (period_l_wr_strobe)

          period_l_register <= writedata;

end

 

寄存器读:

先通过多路选择器,在将选中寄存器在always中同步赋值

  assign read_mux_out = ({16 {(address == 2)}} & period_l_register) |

    ({16 {(address == 3)}} & period_h_register) |

({16 {(address == 1)}} & control_register) |);

 

  always @(posedge clk or negedge reset_n)

    begin

      if (reset_n == 0)

          readdata <= 0;

      else if (read)

          readdata <= read_mux_out;

    end

*博客内容为网友个人发布,仅代表博主个人观点,如有侵权请联系工作人员删除。

参与讨论
登录后参与讨论
推荐文章
最近访客