热度 26
2016-2-5 01:07
6070 次阅读|
0 个评论
移位寄存器与串并转换 实验目的 : ( 1 )用位拼接操作符实现移位寄存器(注意区分左移与右移); ( 2 )利用移位寄存器实现串 — 并转换,从当前工程的根目录下的 data.txt 文本中读取数据,作为串 — 并转换器的输入比特流,然后将这些串行输入的比特流转换为每组有 8bit 的数据; ( 3 )学会使用文件控制任务 $readmemb ,完成存储器变量(寄存器组)的初始化; ( 4 )学会写 Modelsim 脚本测试文件,并掌握测试脚本常用的命令及仿真方法。 实验内容及过程 : ( 1 )用位拼接符实现移位寄存器( data_in 是输入的位宽为 1bit 的信号, shift_reg 是位宽为 8bit 的输出变量) 【右移操作】 思想:将每次输入的 data_in 放到 shift_reg 的最高位,同时去掉 shift_reg 的最低位,然后达到向右移位的效果。 shift_reg = {data_in, shift_reg }; // 过程枚举: // 第 1 个时钟周期: (data_in_1,0000000) // 第 2 个时钟周期: (data_in_2,data_in_1,000000) //...... // 第 8 个时钟周期: (data_in_8,data_in_7,data_in_6,data_in_5,data_in_4,data_in_3,data_in_2,data_in_1) 【左移操作】 思想:将每次输入的 data_in 放到 shift_reg 的最低位,同时去掉 shift_reg 的最高位,然后达到向左移位的效果。 shift_reg = {shift_reg , data_in}; // 过程枚举: // 第 1 个时钟周期: (0000000,data_in_1) // 第 2 个时钟周期: (000000,data_in_1,data_in_2) //...... // 第 8 个时钟周期: (data_in_1,data_in_2,data_in_3,data_in_4,data_in_5,data_in_6,data_in_7,data_in_8) ( 2 )串 — 并转换 串 — 并转换是在移位寄存器的基础上实现的,将输入的串行数据 data_in 按照每 8bit 为一组的形式“组装”成新的并行数据。具体而言,就是将 data_in 输入的比特流一位一位地(逐位)送入移位寄存器,然后,串 — 并转换器每 8 个时钟周期读取一次移位寄存器输出端的数据(在这里也就是读 shift_reg 的值, 8 个时钟周期的控制由计数器完成),并将数据按照并行 8bit 的形式输出。 本实验应采用哪种移位操作方式呢?根据串行输入“先传低位,后传高位”的一般规则,故本实验需采用右移操作的方式,将最先送进来的比特放在 shift_reg 的最低位,然后依次按照“由低位至高位”的方式依次存放各比特。实验代码截图如下所示: Testbench 代码如下: 【文件控制任务 $readmemb 】 $readmemb 是专门用作读取文本文件中的二进制数据,并用这些数据初始化存储器变量(寄存器组),如: testbench 代码中的 $readmemb("./data.txt", mem1x16) 语句,它将是用来读取当前 modelsim 工程根目录下的 data.txt 中的数据(数据内容见图 1 所示),然后将这些值赋给 mem1x16 (它是一个有 16 个 1 位位宽的寄存器组)。 说明:上面的 ./data.txt 是相对路径, $readmemb 还可以使用绝对路径。 图 1 data.txt 中的数据 ( 3 )测试脚本的书写 对比传统的鼠标点击方式和使用测试脚本运行仿真,后者较前者更加快速和便捷,在提高调试代码的效率的同时,提高了仿真的准确性,避免了鼠标点击时易点错或者漏添加文件的现象。总之,使用测试脚本的方式更方便、快捷、高效。 注意:用测试脚本仿真也要先建工程,建完工程就不用管了(不用手动添加文件、编译文件等)。 ① # 号是注释符; ② quit –sim 命令是退出当前仿真(终止仿真过程,关闭仿真窗口,但不关闭当前工程), .main clear 命令是清除命令行显示窗口中的内容; ③ 本实验的测试脚本内容如下: # 退出当前仿真 quit -sim # 清除命令行显示窗口的内容 .main clear # 创建库 lib (就是在当前工程根目录下创建文件夹) vlib lib vlib ./lib/work # 将 work 逻辑库映射到实际的文件路径上来 vmap work ./lib/work # 也可以采用以下的简单用法 # vmap work work # 因为新建仿真工程的时候就自动生成了 work 库和 work 文件夹,所以只需要做简单的映射即可 # 编译(第 2 个 work 是逻辑库的名字, ./ 是当前目录, ../ 是上一目录) vlog -work work ./tb_ex_shift_reg.v vlog -work work ./../design/ex_shift_reg.v # 方法二 -- 用通配符,编译 design 文件夹中的所有 .v 文件(避免反复添加) vlog -work work ./../design/*.v # 启动仿真( -voptargs=+acc 是编译参数,决定是否优化) vsim -voptargs=+acc work.tb_ex_shift_reg # 不带优化的仿真 # vsim -novopt work.tb_ex_shift_reg # 添加波形( tb_ex_shift_reg 是模块名, data_in 是该模块的信号) add wave tb_ex_shift_reg/data_in add wave tb_ex_shift_reg/data_out add wave tb_ex_shift_reg/sclk add wave tb_ex_shift_reg/rst_n add wave tb_ex_shift_reg/mem1x16 # 添加例化模块的信号( ex_shift_reg_inst 是例化的模块名) add wave tb_ex_shift_reg/ex_shift_reg_inst/* run 1us 仿真波形图如图 2 所示: 图 2 仿真波形图 由图 2 可知,串 — 并转换后的数据通过 data_out 输出,先输出的是 01010101 ( 0x55 ),后输出的是 00010001 ( 0x11 ),这与 data.txt 中的数据是一致的—— data.txt 中的存放顺序是 1010101010001000 ,经过串 — 并转换后,变为了 0101010100010001 ,因“低位先传,高位后传”的原因发生了逆序,但仿真结果与我们的设计初衷是一致的,故仿真验证通过。