【Verilog HDL 训练】第 07 天(串并转换)
串并转换
1. 复习verilog语法
【选做题】
- 文件操作fopen fdisplay fwrite fclose
- 生成随机数 random
- 初始化 readmemh readmemb - finish stop
这几个我真没用过,先给一个优秀的链接:FPGA篇(四)Verilog系统函数介绍($display,$fopen,$fscanf,$fwrite($fdisplay),$fclose,$random,$stop)
再借鉴一篇:
本题借鉴别人的:verilog-day7.md
文件操作fopen fdisplay fwrite fclose
integer fileunder;fileunder = $fopen("FileName");//打开文件,返回一个整型,会清空文件$fdisplay(fileunder,"%d",mumber);//写入操作,写完换行$fwrite(fileunder,"%d",mumber);//写入操作,写完不换行$fclose(fileunder);//关闭文件
生成随机数random
每次调用
$random
任务时,它返回一个32位带符号的随机整数。将$random
放入{}内,可以得到非负整数。$random(seed)
中的seed是一个整数,用于指出随机数的取值范围。rand = $random % 60;//给出了一个范围在-59到59之间的随机数。rand = {$random} % 60;//通过位并接操作产生一个值在0到59之间的数。rand = min+{$random} % (max-min+1);//产生一个在min, max之间随机数的例子。
初始化 readmemh readmemb
把文本文件的数据读到存储器阵列中,以对存储器阵列完成初始化。
$readmemb("<数据文件名>",<存储器名>);$readmemb("<数据文件名>",<存储器名>,<起始地址>);$readmemb("<数据文件名>",<存储器名>,<起始地址>,<终止地址>);$readmemh("<数据文件名>",<存储器名>);$readmemh("<数据文件名>",<存储器名>,<起始地址>);$readmemh("<数据文件名>",<存储器名>,<起始地址>,<终止地址>);$readmemb中要求数据必须为二进制,$readmemh要求数据必须为十六进制
finish stop
$stop
:用于在仿真时,暂停仿真。运行到$stop
的时候,仿真会暂停;此时可以在命令行输入run继续运行仿真。$finish
:仿真停止。运行到$finish
的时候,仿真停止退出,此时不可以再继续运行
2. 用verilog实现串并变换。
input [3:0] data_in; output [3:0] data_out; input [1:0] mode; input clk; input rst_n;
mode 0 :串行输入data_in[0],并行输出data_out[3:0]
mode 1 :并行输入data_in[3:0],串行输出data_out[0]
mode 2 :并行输入data_in[3:0],并行输出data_out[3:0],延迟1个时钟周期
mode 3 :并行输入data_in[3:0],并行反序输出data_out[3:0],延迟1个时钟周期并且交换bit顺序
data_out[3]=data_in[0];
data_out[2]=data_in[1]
data_out[1]=data_in[2]
data_out[0]=data_in[3]
附加要求【选做】 将输入输出的位宽做成参数化
先写一个四选一的多路选择器,供顶层文件使用:
`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 2019/05/03 13:46:33
// Design Name:
// Module Name: mux2b
//module mux2b #(parameter N = 4) (input [1 : 0]mode,input [N-1 : 0] a,input [N-1 : 0] b,input [N-1 : 0] c,input [N-1 : 0] d,output reg [N-1 : 0] data_out);localparam M0 = 2'b00, M1 = 2'b01, M2 = 2'b10, M3 = 2'b11;always @ (*) begincase(mode)M0: data_out = a;M1: data_out = b;M2: data_out = c;M3: data_out = d;default: ;endcaseendendmodule
顶层文件:
`timescale 1ns / 1ps
//
// Create Date: 2019/04/30 13:00:03
// Design Name:
// Module Name: Serial2Parallel
// Revision 0.01 - File Created
// Additional Comments:
// 2. 用verilog实现串并变换。/* input [3:0] data_in; output [3:0] data_out; input [1:0] mode; input clk; input rst_n;mode 0 :串行输入data_in[0],并行输出data_out[3:0] mode 1 :并行输入data_in[3:0],串行输出data_out[0]mode 2 :并行输入data_in[3:0],并行输出data_out[3:0],延迟1个时钟周期 mode 3 :并行输入data_in[3:0],并行反序输出data_out[3:0],延迟1个时钟周期并且交换bit顺序 data_out[3]=data_in[0];data_out[2]=data_in[1] data_out[1]=data_in[2] data_out[0]=data_in[3] 附加要求【选做】 将输入输出的位宽做成参数化 */
//module Serial2Parallel #(parameter N = 4) (input [N-1:0] data_in,input [1:0] mode,input clk,input rst_n,output [N-1:0] data_out);localparam M0 = 2'b00, //mode 0 :串行输入data_in[0],并行输出data_out[3:0] M1 = 2'b01, //mode 1 :并行输入data_in[3:0],串行输出data_out[0]M2 = 2'b10, //mode 2 :并行输入data_in[3:0],并行输出data_out[3:0],延迟1个时钟周期 M3 = 2'b11; //mode 3 :并行输入data_in[3:0],并行反序输出data_out[3:0],延迟1个时钟周期并且交换bit顺序 reg [N-1:0] data_out_mid0, data_out_mid1,data_out_mid2,data_out_mid3;integer i;//----------------------------------------------------------------
//en0上升沿检测reg en0;reg en0_r0,en0_r1;always @ (posedge clk or negedge rst_n) beginif(!rst_n) beginen0 <= 0;en0_r0 <= 0;en0_r1 <= 0;endelse beginen0_r0 <= en0;en0_r1 <= en0_r0;endendwire pos0_en,pos0_en1;assign pos0_en = ~en0_r0 & en0;assign pos0_en1 = ~en0_r1 & en0_r0;//en1上升沿检测reg en1;reg en1_r0,en1_r1;always @ (posedge clk or negedge rst_n) beginif(!rst_n) beginen1 <= 0;en1_r0 <= 0;en1_r1 <= 0;endelse beginen1_r0 <= en1;en1_r1 <= en1_r0;endendwire pos1_en,pos1_en1;assign pos1_en = ~en1_r0 & en1;assign pos1_en1 = ~en1_r1 & en1_r0;//en2上升沿检测reg en2;reg en2_r0,en2_r1;always @ (posedge clk or negedge rst_n) beginif(!rst_n) beginen2 <= 0;en2_r0 <= 0;en2_r1 <= 0;endelse beginen2_r0 <= en2;en2_r1 <= en2_r0;endendwire pos2_en,pos2_en1;assign pos2_en = ~en2_r0 & en2;assign pos2_en1 = ~en2_r1 & en2_r0;//----------------------------------------------------------------------- always@(posedge clk or negedge rst_n) beginif(!rst_n) begindata_out_mid0 <= 0;data_out_mid1 <= 0;data_out_mid2 <= 0;data_out_mid3 <= 0;endelse begincase(mode)M0: begindata_out_mid0 <= {data_out_mid0[N-2:0],data_in[0]};//每次输入一位data_in[0]endM1: beginif(pos0_en) begindata_out_mid1 <= data_in;endelse if(pos0_en1)begindata_out_mid1 <= data_out_mid1;endelse begindata_out_mid1 <= {data_out_mid1[0],data_out_mid1[N-1:1]};endendM2: beginif(pos1_en) begindata_out_mid2 <= data_in;endelse if(pos1_en1)begindata_out_mid2 <= data_out_mid2;endendM3: beginif(pos2_en) begindata_out_mid3 <= data_in;endelse if(pos2_en1)begin//genvar i;//generate for(i = 0; i < N; i = i + 1) begin data_out_mid3[i] <= data_out_mid3[N-1-i]; end //endgenerateendenddefault: ;endcaseendendalways @ (*) begincase(mode)M0:;M1: en0 = 1;M2: en1 = 1;M3: en2 = 1;default: ;endcaseendmux2b #(.N(4)) u_data_out(.mode(mode),.a(data_out_mid0), //mode0.b(data_out_mid1), //mode1.c(data_out_mid2), //mode2.d(data_out_mid3), //mode3.data_out(data_out));endmodule
给出测试文件:
`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 2019/04/30 21:17:46
// Design Name:
// Module Name: Serial2Parallel_tb
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//module Serial2Parallel_tb();reg clk, rst_n;reg [3:0] data_in;reg [1:0] mode;wire data_out;localparam M0 = 2'b00, //mode 0 :串行输入data_in[0],并行输出data_out[3:0] M1 = 2'b01, //mode 1 :并行输入data_in[3:0],串行输出data_out[0]M2 = 2'b10, //mode 2 :并行输入data_in[3:0],并行输出data_out[3:0],延迟1个时钟周期 M3 = 2'b11; //mode 3 :并行输入data_in[3:0],并行反序输出data_out[3:0],延迟1个时钟周期并且交换bit顺序 initial clk = 0;always begin#1 clk = ~clk;endinitial beginrst_n = 0;#3rst_n = 1;mode = M0;data_in = 4'b0001;#2 data_in = 4'b0000;#2 data_in = 4'b0001;#2data_in = 4'b0000;#2 data_in = 4'b0001;#5mode = M1;data_in = 4'b0100;#12mode = M2;data_in = 4'b0010;#6mode = M3;data_in = 4'b1010;endSerial2Parallel #(.N(4)) u0(.clk(clk),.rst_n(rst_n),.mode(mode),.data_in(data_in),.data_out(data_out));endmodule
下面给出行为仿真波形图:
模式0:
由于输入是data_in[0],所有data_in[0]单独显示也许会更好:
由仿真图可见,我们的串行输入为1010111,而输出为0001,0010,0101,1010,0101,1011,0111,符合我们的并行输出。
模式0的串行输出正确。
模式1:
模式一为并行输入,串行输出,输出为data_out[0],就是上图中的[0],模式1从16ns处开始,在17ns时刻(时钟上升沿)给数据,缓冲一个周期,到19ns开始输出,输出为0010;因为输入从低到高为0010,故输出4个即可,其他输出均不是我们要的。
模式2:
模式2是并行输入,并行输出:
模式2从28ns处开始,在29ns处(时钟有效沿)给数据31ns处输出数据data_out为0010;
模式3:
模式3为并行输入,并行输出,但是反向输出,例如输入为data_in = 4'b1010,则输出data_out=4'b0101;
模式3从34ns开始,35ns给数据从低到高为0101,延迟一拍,输出为1010,满足要求。
总结:代码需要多些,多学习一些技巧,这次写的这个代码,我自己是很不满意的,因为有很多缺陷,并不能完美的实现所要的功能(例如,输出延迟一拍,那一拍之前的输出是什么?是不是应该不输出,设为高阻态),但碍于见识少等,这种困惑并不能在代码中体现。
3. 记录一下第2题中用到的工具,包括工具版本,操作步骤或命令选项,遇到的错误,提示信息等。比较一下,与昨天的记录有何相同,有何不同。
Vivado 2018
这次的代码设计用了不少时间,因为加入了mode,模式之间的切换是一个需要考虑的难点。第二道题,确实也让我学到了一些东西,这都可以成为经验,我一开始的设计,最后的data_out输出并没有使用多路选择器来实现,而是如下:
assign data_out = data_out_mid0;
assign data_out = data_out_mid1;
等
我现在看起来确实可笑,但是当时并没有想到,我在相关群里咨询了大佬们,大佬们一眼就看出来了问题,确实感谢它们。
上述写法,data_out和这么多变量相连,到底输出取谁呢?想想都知道走火入魔了。
但最终的整体程序,还是个人最初的思想,加以修改。
这肯定不是最好的写法,还是要想别人学习。多见识见识电路实现的技巧。
最后一个简单的问题就是,我调试代码中犯的一个小错误,就是在多路选择器的代码中,忘了给mode位数声明,导致后面的功能出现问题,后来通过仿真图及时发现并得以改正。
【Verilog HDL 训练】第 07 天(串并转换)相关推荐
- 【Verilog HDL 训练】第 11 天(分频电路)
设计一个占空比50%的三分频电路. 针对这个分频器,博文的末尾会给出一个反面教材,这是我上次写的一个分频器,看起来很好,其实是不能综合的.针对其中的错误,我令立博文记录之:[ Verilog ]alw ...
- 【Verilog HDL 训练】第 06 天(边沿检测)
1. 复习verilog语法 [选做题] - reg和wire的区别 寄存器数据类型 Verilog中规定,凡是在程序块中被赋值的变量,都必须是寄存器类型的.(程序块:例如always块) 这里未免还 ...
- 【Verilog HDL 训练】第 09 天(按键消抖)
5月7日 按键防抖 1. 用verilog实现按键抖动消除电路,抖动小于15ms,输入时钟12MHz. 在编写Verilog代码之前,先分析下一些前提问题,首先是几个按键(1个,多个),我们以1个和三 ...
- c语言实现按键的抖动与消除,【Verilog HDL 训练】第 09 天(按键消抖)
5月7日 按键防抖 1. 用verilog实现按键抖动消除电路,抖动小于15ms,输入时钟12MHz. 在编写Verilog代码之前,先分析下一些前提问题,首先是几个按键(1个,多个),我们以1个和三 ...
- 【Verilog HDL 训练】第 14 天(glitch-free的两个时钟切换电路)
2019年5月13日 glitch-free的两个时钟切换电路. 可以看到这是一个星期之前的题目了,现在才抽空做,把这篇颠倒个顺序吧,也是最后一天了,以后的题目都是讨论性质的,不会以第多少天的形式来写 ...
- 【Verilog HDL 训练】第 13 天(存储器、SRAM)
存储器. 1. rom,ram,flash,ddr,sram,dram,mram..列举并解释一下这些名词. 2. 用verilog实现一个深度为16,位宽8bit的单端口SRAM.搭建一个仿真环境, ...
- 【Verilog HDL 训练】第 10 天(PWM 呼吸灯)
5月8日 PWM 用verilog实现PWM控制呼吸灯.呼吸周期2秒:1秒逐渐变亮,1秒逐渐变暗.系统时钟24MHz,pwm周期1ms,精度1us. 今天的题目我是第一次见,答案借鉴大神的:Veril ...
- 【Verilog HDL 训练】第 08 天(二进制、Johnson、环形计数器)
5月6日 计数器 1. 用verilog实现一个4bit二进制计数器. a) 异步复位 b) 同步复位 input clk, rst_n; output [3:0] o_cnt; Verilog实现代 ...
- 【Verilog HDL 训练】第 05 天(序列检测)
1. dff和latch有什么区别. 锁存器是一种对脉冲电平(也就是0或者1)敏感的存储单元电路,而触发器是一种对脉冲边沿(即上升沿或者下降沿)敏感的存储电路. "触发器" 泛指一 ...
最新文章
- Axis2 -POJO
- SAP CRM Fiori应用My Opportunity标题显示不正确的问题分析
- Maze(BFS处理)
- 对安装好的hadoop集群做个测试
- dell m610刀片查看日志及更换内存
- 升级win11-需要开启主板的tpm2.0
- 聪明贝塔(Smart Beta)
- 固态硬盘安装记录之数据二次迁移
- 使用 OpenSSL 生成 HTTPS 证书
- 【FastDFS】分布式文件系统FastDFS之FastDHT文件去重
- pytest框架之fixture测试夹具详解
- 他如何从一位专车司机成功变身CEO?
- Python —对象的浅拷贝和深拷贝
- php加波浪线不解析,给文字加波浪线效果
- Mysql 带条件计数
- 【Unity开发小技巧】iOS APP下载安装时,如果出现此时无法下载安装APP的字样时,一些解决思路
- Arduino MEGA2560与蓝牙的通信(玄学)问题
- 什么是XML?如何学习XML?
- JZ73 翻转单词序列
- 王者显示重连服务器失败,最强王者三国手游服务器连接失败 最强王者三国手游曹操学什么技能...
热门文章
- VLAN+DHCP(1)(附抓包)
- oracle运行企业管理器,如何打开Oracle 10g的企业管理器(Enterprise Manager)?
- 修改所有列_宝塔面板安装完的一些列操作
- python语言包含的错误,Python语言程序中包含的错误,一般分为三种,以下____________不是其中的一种...
- 电子计算机说明文作文,电脑事物说明文
- 山西电大统考英语和计算机试题,2017年电大统考计算机试题及答案.doc
- SpringCloud服务注册启动的时候报错(com.sun.jersey.api.client.ClientHandlerException: java.net.ConnectException)
- 怎么解释三线圈直流电机工作原理更好?
- 当周期信号的频率趋向无穷时,它将消失
- 关于第十六届全国大学生智能汽车竞赛总决赛的规则建议