模型功能
- 实现寄存器之间的连线
- 实现寄存器的声明
- 建构时钟的时序系统
模型框图
`timescale 1ns / 1ps
/*
*/
// *******************************************************************************
// Company: Fpga Publish
// Engineer: FP
//
// Create Date: 2024/03/24 12:39:43
// Design Name:
// Module Name: verilog_demo
// Project Name:
// Target Devices: ZYNQ7010 | XCZU2CG | Kintex7
// Tool Versions: 2021.1 || 2022.2
// Description:
// *
// Dependencies:
// *
// Revision: 0.01
// Revision 0.01 - File Created
// Additional Comments:
//
// *******************************************************************************
module verilog_demo #(
//mode
parameter MD_SIM_ABLE = 0,
//number
parameter NB_DELAY_CLK = 100,
//width
parameter WD_ERR_INFO = 4
)(
//! system signals
input i_sys_clk ,
input i_sys_resetn,
//! @virtualbus uart_interface @dir out
output m_uart_0_mtx, //! uart master tx
input m_uart_0_mrx, //! uart master rx
//! @end
//! error info feedback
output [WD_ERR_INFO-1:0] m_err_verilog_info1
);
//========================================================
//function to math and logic
//========================================================
//localparam to converation and calculate
//========================================================
//register and wire to time sequence and combine
// ----------------------------------------------------------
// demo variable
reg [1:0] r_dat0 = 0;
reg signed [1:0] r_dat1 = 0;
wire [1:0] w_dat2;
reg [1:0] r_fifo [0:1]
wire [1:0] w_array [0:1];
//========================================================
//always and assign to drive logic and connect
//========================================================
//module and task to build part of system
//========================================================
//expand and plug-in part with version
//========================================================
//ila and vio to debug and monitor
endmodule
/* end verilog
*/
实现步骤
- 声明寄存器
- reg类型变量实际上是对FF(除法器)的快速声明方法
- 使用FDCE的原语可以实现寄存器的准确描述,但是比较少用
FDCE #(
.INIT(1'b0), // Initial value of register, 1'b0, 1'b1
// Programmable Inversion Attributes: Specifies the use of the built-in programmable inversion
.IS_CLR_INVERTED(1'b0), // Optional inversion for CLR
.IS_C_INVERTED(1'b0), // Optional inversion for C
.IS_D_INVERTED(1'b0) // Optional inversion for D
)
FDCE_inst (
.Q(Q), // 1-bit output: Data
.C(C), // 1-bit input: Clock
.CE(CE), // 1-bit input: Clock enable
.CLR(CLR), // 1-bit input: Asynchronous clear
.D(D) // 1-bit input: Data
);
- 其中位宽的作用是声明多个FDCE组合成寄存器组,实现多bit数据的处理
- 默认值的就是快速输入原语中的INIT值
- 原语中的其他描述则会在always逻辑中体现,本章不展开
- wire线的连接
- 从硬件上理解,wire就是各个器件之间的走线
- 从高级语言的角度理解,wire就是等式的右边部分的缩写
- 也就是说,wire并不是C语言中的变量,而是等式的右边,用于描述某些中间过程
- 二维reg变量的使用
- 如模型描述中的r_fifo,可以允许输入地址去访问类数组结构
- 该二维reg变量实际上依靠DRAM实现,地址由查找表实现,受限于查找表的大小一般为64bit,所以二维变量地址不能太大
- 一般器件将地址深度控制在256以内,这个和器件底层LUT级联单元有关(当然也和时序有关,时序要求越低,支持数目越多)
- 需要注意的是,严禁使用三维reg变量
- 三维reg变量是指地址受到两个reg变量的访问
- 从其映射关系可以知道,三维reg变量形成的是两个reg变量位宽相乘的查找表数量
- 除非两个变量的位宽都很小,且时序要求很低,否则极有可能出现计算异常(本人已经多次验证过,仿真没有问题,但是实际运行异常)
- 而且,可以通过简单地提前一个周期计算地址的方法完成维度的降低,完全没有必要使用这种延时大、条件严格的结构
- 二维阵列的使用
- 如模型描述的w_array,可以允许输入地址去访问数据的特定位宽
- 是的,和二维变量的区别是,w_array是走线集合,而不是硬件结构
- wire [8-1:0] x [0:2-1] 和 wire [8*2-1:0]属于一个性质,只不过对应关系有所差异
- 一般二维阵列就是配合二维变量,在级联结果中形成同步的信号缓存
- 级联一维变量的使用
- 并不是所有类似r_fifo的变量都是二维reg变量
- 这个取决于该变量的地址控制方式
- 当使用常数控制地址访问时,其更多是作为级联变量使用
- 但是从使用效果来说,和二维变量无区别,所以可以全部用fifo进行标记
- 在本集合的第三篇时就使用过级联变量,本质上也是一种缩写,而非特殊的硬件结构
- 寄存器之间的传递
- 理论上,可以使用reg完成所有的寄存器的描述
- 但是为了灵活,还是需要用wire缓存一些中间结果,以免出现大量的重复代码
- 也就是存在下列传递关系:
- reg --> wire (assign)
- wire --> reg (always)
- wire --> wire (assign)
- reg --> reg (always)
- 端口列表在传递时均为wire,可以直接连接,通过input和output进行方向区分
最终效果
module adder_cascade#(
parameter NB_CASCADE = 4,
parameter WD_DAT = 4
)(
input i_clk,
input [WD_DAT-1:0] a,
output [WD_DAT-1:0] s,
output [WD_DAT*NB_CASCADE-1:0] o_dat
);
wire [WD_DAT-1:0] a_array [0:NB_CASCADE]; //add 1 bit for input
reg [WD_DAT-1:0] r_fifo [0:NB_CASCADE-1]; //add 1 bit for input
assign a_array[0] = a;
assign s = a_array[NB_CASCADE];
generate genvar i;
for(i = 0; i < NB_CASCADE; i = i + 1)
begin: FOR_NB_CASCADE
adder #(
.WD_DAT(WD_DAT)
)u_adder(
.a(a_array[i]),
.s(a_array[i+1])
);
always@(posedge i_clk)
begin
r_fifo[i] <= a_array[i];
end
assign o_dat[WD_DAT*(i+1)-1:WD_DAT*i] = r_fifo[i];
end
endgenerate
endmodule
调用接口
- 非封装模型,无调用接口