Verilog功能模块——符号位扩展

本文详细介绍了如何处理DDR等32/64位存储器中的数据转换,通过符号位扩展技术实现二进制补码的扩展,提供模块代码、testbench及Vivado模拟验证。阅读者将了解补码扩展原理和实战应用实例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一. 模块功能与应用场景

模块功能:符号位扩展

应用场景:DDR等存储器通常是32/64位的,数据需要转为合适的位数再存入。


二. 模块框图与使用说明

signExtension

输入和输出都是二进制补码,补码的符号位扩展就是补最高位即符号位即可


三. 模块代码

/*
 * @Author       : Xu Dakang
 * @Email        : XudaKang_up@qq.com
 * @Date         : 2021-05-14 09:50:48
 * @LastEditors  : Xu Dakang
 * @LastEditTime : 2021-05-14 22:59:16
 * @Filename     : signExtension.v
 * @Description  : 符号位扩展模块
*/

/*
* 思路: 输入数据为二进制补码,判断输入数据的最高位,为1则高位补1,为0则高位补0;
*/



module signExtension
#(
  parameter INPUT_WIDTH  = 24,
  parameter OUTPUT_WIDTH = 32
)(
  input  wire signed [INPUT_WIDTH-1  : 0] input_number,
  output wire signed [OUTPUT_WIDTH-1 : 0] output_number
);



assign output_number = {{(OUTPUT_WIDTH - INPUT_WIDTH){input_number[INPUT_WIDTH-1]}}, input_number};



endmodule

四. testbench

/*
 * @Author       : Xu Dakang
 * @Email        : XudaKang_up@qq.com
 * @Date         : 2021-05-14 19:40:46
 * @LastEditors  : Xu Dakang
 * @LastEditTime : 2021-05-14 22:58:24
 * @Filename     : signExtension_tb.sv
 * @Description  : testbench of signExtension
*/



module signExtension_tb();

timeunit 1ns;
timeprecision 10ps;

parameter INPUT_WIDTH  = 24;
parameter OUTPUT_WIDTH = 32;

logic signed [INPUT_WIDTH-1  : 0] input_number;
logic signed [OUTPUT_WIDTH-1 : 0] output_number;



signExtension  signExtension_inst(.*);



// 生成时钟
localparam CLKT = 2;
logic clk;
initial begin
  clk = 0;
  forever #(CLKT / 2) clk = ~clk;
end



initial begin
  input_number = 12;
  #CLKT;
  input_number = 88;
  #CLKT;
  input_number = -18;
  #CLKT;
  input_number = -300;
  #CLKT;
  input_number = 24'hXX8CX2;
  #CLKT;
  $stop;
end



endmodule

五. 仿真验证

仿真工具:Vivado 2020.2 Simulator。

16进制显示:

有符号10进制显示:


六. 工程分享

signExtension 符号位扩展模块 vivado 2020.2工程.7z

欢迎大家关注我的公众号:徐晓康的博客,回复以下代码获取。

1375

建议复制过去不会码错字!


徐晓康的博客持续分享高质量硬件、FPGA与嵌入式知识,软件,工具等内容,欢迎大家关注。

### SystemVerilog 中的拼接符号用法 在 SystemVerilog 中,拼接符号 `{}` 被广泛应用于位级操作,主要用于将多个信号组合成一个更大的向量或将单个信号拆分为更小的部分。这种语法非常灵活,适用于多种场景。 #### 基本定义 拼接符号 `{}` 是一种强大的工具,允许开发者通过指定顺序来创建新的位矢量[^2]。它不仅可以用于简单的信号连接,还可以与其他常数或表达式一起使用。 #### 示例代码 以下是几个常见的使用案例: ```systemverilog // 将两个信号 a 和 b 进行拼接 logic [7:0] a; logic [7:0] b; logic [15:0] c; assign c = {a, b}; // 结果是一个 16 位宽的信号,其中高字节来自 a,低字节来自 b // 添加常数值进行拼接 logic [3:0] d; logic [7:0] e; assign e = {4'd0, d}; // 在 d 的高位填充 4 个零,形成一个新的 8 位信号 // 复制操作符的应用 (replication operator) logic [3:0] f; logic [11:0] g; assign g = {3{f}}; // 将 f 的值重复三次并拼接在一起,形成一个 12 位宽的信号 ``` #### 特殊情况说明 当涉及到复杂的硬件描述时,拼接符号可以用来实现特定的功能需求。例如,在某些情况下可能需要对输入信号重新排列或者扩展其宽度。 #### 动态数组与拼接 虽然动态数组本身并不直接涉及拼接符号,但在实际应用中两者经常结合使用。比如可以通过先构建一个动态数组再利用拼接将其转换为固定长度的寄存器形式[^4]。 ```systemverilog dynamic logic [7:0] array []; array = new[3]; array[0] = 8'hFF; array[1] = 8'hAA; array[2] = 8'h55; logic [23:0] result; assign result = {>>{array}}; // 使用流平展操作符 >>{} 将动态数组的内容按序展开为单一向量 ``` 以上展示了如何运用 `{}` 来完成不同类型的信号处理任务,并且强调了该特性对于 RTL 设计的重要性。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值