HDLBits——Module

本文深入探讨了HDL中模块连接的两种主要方法:位置匹配和名称匹配,并通过实例对比了‘偷懒法’与‘常规法’的优劣,强调了在实际编程中采用‘常规法’的重要性和优势。

本人持续更新HDLBits其他题目,详细讲解我们编程时会遇到的各种错误,若有兴趣可以移步我的博客中心浏览本人的其他文章,感谢赏光!

原题如下

在这里插入图片描述在这里插入图片描述
在这里插入图片描述
这道题的本质就是内部的module 和top_module的连接问题。
众所周知,信号连接有两种方式,一种是根据位置来摆放,一种是根据名称来直接连接而与位置无关,接下来我就用代码来帮大家解释解释。
假如我们有一个模块(instance) mod_a(output out,input in1,input in2) 而我有一个顶层文件top_mod(input a,input b,output out)
我有两种方式将他们连接
1、偷懒法mod_a instance1(in1,in2,out); 因为在top_mod(1,2,3)我们可以发现1位置是a,2位置是输入b,3位置是输出out,所以我们mod_a instance1(4,5,6)位置对应连接的就是(1,2,3)三个位置,分别是1连接4,2连接5,3连接6。
2、常规法 常规法mod_a instance2(.out(out),.in1(a), .in2(b)); 就是我们这样连接,.out(out),.in1(a), .in2(b) 没有括号的out ,in1,in2,是mod_a,而在括号内部的是顶层模块的引脚out、a、b。

常规法可以把内部的引脚顺序打乱如mod_a instance2(.in1(a), .out(out),.in2(b)); 然而“偷懒法”却不可以

一般我们采用常规法进行连接,这样不用担心顺序问题,而且引脚的连接情况也一目了然

在 Linux 内核中,`THIS_MODULE` 是一个用于表示当前模块的宏,其定义位于 `<linux/module.h>` 中。它通常用于模块初始化和卸载时的注册与注销操作,提供了一个指向 `struct module` 的指针,表示当前正在运行的模块结构体。 在 SCSI 子系统中,`scsi_register_driver` 函数用于注册一个 SCSI 驱动程序。该函数需要传入一个 `struct scsi_driver` 类型的指针,并且在内部会调用 `driver_register` 来完成实际的驱动注册操作。在调用 `scsi_register_driver` 时,通常会使用 `THIS_MODULE` 作为参数之一,以确保驱动程序与模块生命周期同步。 例如,一个典型的 SCSI 驱动程序初始化函数可能如下所示: ```c static int __init my_scsi_driver_init(void) { return scsi_register_driver(&my_scsi_driver); } module_init(my_scsi_driver_init); ``` 其中,`scsi_register_driver` 内部实现可能类似于: ```c int scsi_register_driver(struct scsi_driver *sdrv) { sdrv->driver.owner = THIS_MODULE; return driver_register(&sdrv->driver); } ``` 通过将 `THIS_MODULE` 赋值给 `driver.owner`,确保了该驱动所属的模块不会在驱动被使用时被卸载[^1]。 在内核模块机制中,`THIS_MODULE` 的定义如下: ```c extern struct module __this_module; #define THIS_MODULE (&__this_module) ``` 每个模块在加载时都会有一个对应的 `struct module` 结构体,`THIS_MODULE` 提供了对该结构体的引用,用于模块的引用计数、符号导出、模块卸载同步等机制[^2]。 ### `THIS_MODULE` 的主要用途包括: - **模块引用计数**:当一个设备驱动程序被注册时,内核会增加该模块的引用计数,防止模块在被使用时被卸载。 - **符号导出**:模块中导出的符号(如函数、变量)需要与模块结构体关联,`THIS_MODULE` 用于标识这些符号属于哪个模块。 - **模块卸载同步**:在卸载模块时,内核会检查模块的引用计数,若仍有设备在使用该模块,则不允许卸载。 在 `scsi_register_driver` 中使用 `THIS_MODULE` 的目的正是为了确保 SCSI 驱动程序在其生命周期内始终与模块绑定,防止模块在驱动程序仍处于活动状态时被卸载,从而避免潜在的空指针访问或内存泄漏问题。 ### 示例代码:SCSI 驱动程序注册 ```c #include <linux/module.h> #include <scsi/scsi_driver.h> static struct scsi_driver my_scsi_drv = { .driver = { .name = "my_scsi_driver", .owner = THIS_MODULE, }, // 其他驱动操作函数 }; static int __init my_scsi_init(void) { return scsi_register_driver(&my_scsi_drv); } static void __exit my_scsi_exit(void) { scsi_unregister_driver(&my_scsi_drv); } module_init(my_scsi_init); module_exit(my_scsi_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Your Name"); MODULE_DESCRIPTION("A simple SCSI driver example"); ``` ### 总结 - `THIS_MODULE` 是当前模块的引用,用于模块注册、符号导出和引用计数管理。 - 在 `scsi_register_driver` 中使用 `THIS_MODULE` 可确保驱动程序与模块生命周期同步,防止模块在驱动程序仍在使用时被卸载。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值