串并转换

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 天(串并转换)相关推荐

  1. 【Verilog HDL 训练】第 11 天(分频电路)

    设计一个占空比50%的三分频电路. 针对这个分频器,博文的末尾会给出一个反面教材,这是我上次写的一个分频器,看起来很好,其实是不能综合的.针对其中的错误,我令立博文记录之:[ Verilog ]alw ...

  2. 【Verilog HDL 训练】第 06 天(边沿检测)

    1. 复习verilog语法 [选做题] - reg和wire的区别 寄存器数据类型 Verilog中规定,凡是在程序块中被赋值的变量,都必须是寄存器类型的.(程序块:例如always块) 这里未免还 ...

  3. 【Verilog HDL 训练】第 09 天(按键消抖)

    5月7日 按键防抖 1. 用verilog实现按键抖动消除电路,抖动小于15ms,输入时钟12MHz. 在编写Verilog代码之前,先分析下一些前提问题,首先是几个按键(1个,多个),我们以1个和三 ...

  4. c语言实现按键的抖动与消除,【Verilog HDL 训练】第 09 天(按键消抖)

    5月7日 按键防抖 1. 用verilog实现按键抖动消除电路,抖动小于15ms,输入时钟12MHz. 在编写Verilog代码之前,先分析下一些前提问题,首先是几个按键(1个,多个),我们以1个和三 ...

  5. 【Verilog HDL 训练】第 14 天(glitch-free的两个时钟切换电路)

    2019年5月13日 glitch-free的两个时钟切换电路. 可以看到这是一个星期之前的题目了,现在才抽空做,把这篇颠倒个顺序吧,也是最后一天了,以后的题目都是讨论性质的,不会以第多少天的形式来写 ...

  6. 【Verilog HDL 训练】第 13 天(存储器、SRAM)

    存储器. 1. rom,ram,flash,ddr,sram,dram,mram..列举并解释一下这些名词. 2. 用verilog实现一个深度为16,位宽8bit的单端口SRAM.搭建一个仿真环境, ...

  7. 【Verilog HDL 训练】第 10 天(PWM 呼吸灯)

    5月8日 PWM 用verilog实现PWM控制呼吸灯.呼吸周期2秒:1秒逐渐变亮,1秒逐渐变暗.系统时钟24MHz,pwm周期1ms,精度1us. 今天的题目我是第一次见,答案借鉴大神的:Veril ...

  8. 【Verilog HDL 训练】第 08 天(二进制、Johnson、环形计数器)

    5月6日 计数器 1. 用verilog实现一个4bit二进制计数器. a) 异步复位 b) 同步复位 input clk, rst_n; output [3:0] o_cnt; Verilog实现代 ...

  9. 【Verilog HDL 训练】第 05 天(序列检测)

    1. dff和latch有什么区别. 锁存器是一种对脉冲电平(也就是0或者1)敏感的存储单元电路,而触发器是一种对脉冲边沿(即上升沿或者下降沿)敏感的存储电路. "触发器" 泛指一 ...

最新文章

  1. Axis2 -POJO
  2. SAP CRM Fiori应用My Opportunity标题显示不正确的问题分析
  3. Maze(BFS处理)
  4. 对安装好的hadoop集群做个测试
  5. dell m610刀片查看日志及更换内存
  6. 升级win11-需要开启主板的tpm2.0
  7. 聪明贝塔(Smart Beta)
  8. 固态硬盘安装记录之数据二次迁移
  9. 使用 OpenSSL 生成 HTTPS 证书
  10. 【FastDFS】分布式文件系统FastDFS之FastDHT文件去重
  11. pytest框架之fixture测试夹具详解
  12. 他如何从一位专车司机成功变身CEO?
  13. Python —对象的浅拷贝和深拷贝
  14. php加波浪线不解析,给文字加波浪线效果
  15. Mysql 带条件计数
  16. 【Unity开发小技巧】iOS APP下载安装时,如果出现此时无法下载安装APP的字样时,一些解决思路
  17. Arduino MEGA2560与蓝牙的通信(玄学)问题
  18. 什么是XML?如何学习XML?
  19. JZ73 翻转单词序列
  20. 王者显示重连服务器失败,最强王者三国手游服务器连接失败 最强王者三国手游曹操学什么技能...

热门文章

  1. VLAN+DHCP(1)(附抓包)
  2. oracle运行企业管理器,如何打开Oracle 10g的企业管理器(Enterprise Manager)?
  3. 修改所有列_宝塔面板安装完的一些列操作
  4. python语言包含的错误,Python语言程序中包含的错误,一般分为三种,以下____________不是其中的一种...
  5. 电子计算机说明文作文,电脑事物说明文
  6. 山西电大统考英语和计算机试题,2017年电大统考计算机试题及答案.doc
  7. SpringCloud服务注册启动的时候报错(com.sun.jersey.api.client.ClientHandlerException: java.net.ConnectException)
  8. 怎么解释三线圈直流电机工作原理更好?
  9. 当周期信号的频率趋向无穷时,它将消失
  10. 关于第十六届全国大学生智能汽车竞赛总决赛的规则建议