看了很多Altera官方的代码,总结了其中的一些比较好的编写形式和技巧,供大家参考。
信号写法<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
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
文章评论(0条评论)
登录后参与讨论