动态选线,动态的选择变量的位宽

一、原理

参考博客:<Verilog> 语法技巧:数据位操作_verilog移位操作-CSDN博客

下图是从作者的博客cv过来的一张图,讲的非常的清晰。实现了动态的选择选择数据的位宽,只需要动态的改变base_expr就可以。

二、在s2p的运用

2.1 部分代码

integer j;
always@(posedge clk or negedge resetn)begin
    // 以parallel_num是8路为例,此时计数器是 8,9,10 11   12,13,14,15  
    if( (cnt >= parallel_num ) && (cnt <= double_parallel_num - 1) )begin
        for (j = 0; j < parallel_num; j = j + 1) begin
            // 用循环拼接,把从0到7的寄存器数组的值都放到s2p里面,有个问题就是,第一个fft部件的输入被放到了高位,
            // 后续给值的时候,需要注意把高位给到第一个fft的输入
            // 另外,通过计数器的增加,可以从左到右边的读取完    前8个寄存器数组地址的[ 63 : 0] ,[127 : 96] ,[191 : 160].....
            
            // s2p_output = {s2p_output, short_fft_buf[j][( (cnt_num - parallel_num) +1)*data_length*2 - 1 : (cnt_num - parallel_num)*data_length*2]};
            // 这里用(cnt + 1)的原因是计数器从7开始,不 +1 就会出现负数
            s2p_output = {s2p_output, short_fft_buf[j][( cnt - parallel_num)*data_length*2  +: data_length*2]};
        end
    end
    // 计数器的值是16的时候,下个周期就可以开始读取刚刚写入的8个数据了
    // short_fft_buf[double_parallel_num - 2] != 0 的作用是防止计数器才从0计数7,就开始尝试读取后8个地址的寄存器数组值,因为这个时候后八个地址还没有写入
    // (cnt == double_parallel_num - 1)的作用是引入计算器的值等于15
    // 计数器的值 0,1,2,3    4,5,6,7
    else if( (cnt >= 0)  && (short_fft_buf[double_parallel_num - 2] != 0)  )begin
        for (j = parallel_num; j < double_parallel_num; j = j + 1) begin
            // 通过计数器的增加,可以从左到右边的读取完    前8个寄存器数组地址的[127 : 64] ,[191 : 160].....
            // 上面已经读取了[ 63  : 0],这里从[127 : 64 ] 开始
            s2p_output = {s2p_output, short_fft_buf[j][ cnt *data_length*2  +: data_length*2]};
        end
    end
end

2.2 报错代码


如果使用下图的方式会显示范围不能是动态的,范围必须是常量,因为引入的计数器是一个变量。

[VRFC 10-1775] range must be bounded by constant expressions


2.3 正确表达

s2p_output = {s2p_output, short_fft_buf[j][( (cnt + 1) - parallel_num)*data_length*2  +: data_length*2]};

上面的代码中,线选部分如下,(cnt+ 1) - parallel_num)*data_length*2 可以根据计算器的变化变化,然后向上选择(+:) 64位。

[( (cnt + 1) - parallel_num)*data_length*2  +: data_length*2]

好处:
1、表达更加简练,不容易出错,例如选择[63: 0],[127 : 64]....,就只需要计算0,64怎么表达出来,不用再计算 63和 127的表达式了。

2、使用情况更广,不会出现上面的报错。

  • 6
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MAX7219是一种常用的点阵LED驱动芯片,可以控制8x8的点阵LED灯组成的字符或图形进行显示。在51单片机上使用MAX7219进行点阵动态显示,需要先编写驱动程序,然后通过串口或者其他输入设备来输入要显示的字符或图形。 以下是一个简单的MAX7219点阵动态显示的程序框架: ```c #include <reg51.h> #include <intrins.h> // MAX7219控制端口定义 sbit MAX7219_CS = P1^0; sbit MAX7219_CLK = P1^1; sbit MAX7219_DIN = P1^2; // MAX7219控制函数 void MAX7219_SendByte(unsigned char data) { unsigned char i; for (i = 8; i > 0; i--) { MAX7219_CLK = 0; // 时钟线拉低 MAX7219_DIN = data & 0x80; // 数据线输出最高位,即先传输高位 data <<= 1; // 数据左移一位,准备传输下一位 MAX7219_CLK = 1; // 时钟线拉高 } } // MAX7219初始化函数 void MAX7219_Init(void) { MAX7219_CS = 1; // 片选线拉高 MAX7219_SendByte(0x0C); // 打开显示,亮度默认 MAX7219_SendByte(0x01); // 显示测试,所有LED点亮 MAX7219_SendByte(0x0F); // 关闭显示,亮度最大 } // 显示字符函数,例如显示字符A void MAX7219_ShowChar(unsigned char row, unsigned char col, unsigned char ch) { unsigned char i; MAX7219_CS = 0; // 片选线拉低 MAX7219_SendByte(col + 1); // 选择列地址 MAX7219_SendByte(ch); // 显示字符 MAX7219_CS = 1; // 片选线拉高 } // 主函数 void main(void) { MAX7219_Init(); // MAX7219初始化 while (1) { // 读取输入字符或图形 // 进行动态显示 } } ``` 在主函数中,可以通过读取输入字符或图形的方式来进行动态显示。例如,可以通过串口发送字符数据,然后在主函数中读取串口接收缓冲区的数据,并将其转换成MAX7219可以显示的格式。然后通过MAX7219_ShowChar函数来进行显示。 需要注意的是,MAX7219的控制方式非常严格,需要按照其规定的时序和数据格式进行控制。因此,在编写MAX7219驱动程序时,需要仔细参考其数据手册,确保控制方式的正确性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值