首页
关于我
友链
小程序
舔狗日记
小黑屋
音乐解锁
阿狸和桃子
Search
1
将校园卡复制到小米手环
25 阅读
2
windows11系统自带VPN连接不上群辉VPN服务器问题
21 阅读
3
使用ESP8266完成校园网WEB认证
19 阅读
4
数字振镜XY2-100协议
17 阅读
5
Verilog中为inout类型赋值
16 阅读
技术
生活
登录
Search
标签搜索
qt
mqtt
FreeRTOS
stm32
iar
VPN
光猫破解
esp8266
群晖
VideoStation
exti
c++
eclipse
bootloader
pixhawk
遥控器
失控保护
ARM
NAS
ENPASS
AMENG
累计撰写
79
篇文章
累计收到
17
条评论
首页
栏目
技术
生活
页面
关于我
友链
推荐
舔狗日记
小黑屋
音乐解锁
阿狸和桃子
搜索到
2
篇与
的结果
2023-08-29
Verilog基础语法
1、基础知识逻辑0:低电平,也就是电路中的GND 逻辑1:高电平,也就是电路中的VCC逻辑X:未知状态,逻辑Z:高阻态,外部没有激励信号,是一个悬空状态 2、数字进制格式、标示符b:表示二进制 o:表示八进制 d:表示十进制 h:表示十六进制 numA=8'b10101010; //8'表示numA这个变量占8位,numA的值是二进制的10101010 numB=4'd2;//numB的值是十进制的2 numC=4'ha;//numC的值是十六进制的A numD=10;//numD占32bit,是十进制的10说明:不指定位宽则默认是32位,不指定进制则默认是十进制 标示符:可用于模块名、端口号、信号名等(类似C的变量名)3、数据类型 寄存器数据类型 (reg)线网数据类型(wire)参数数据类型(parameter)3.1寄存器数据类型关键则:reg 初始值为:不定制X(逻辑X)module test(L); output LED; input num; reg[7:0] LED; //寄存器数据类型 reg num; //寄存器数据类型 always begin LED=8'b10101010; end endmodule3.2 线网数据类型关键字:wire 表示结构实体之间的物理连线线网类型的变量不能村初值,他是由驱动她都元件决定的没有驱动元件连接的线网类型变量是:高阻值(逻辑Z)wire key_flag;3.3 参数类型关键字:parameter 他类似C中的 #define,宏定义4、运算符Verilog中的 算数运算符、关系运算符、逻辑运算符、条件运算符、位运算符、移位运算符包括其 运算符优先级 也与C语言相同。 Verilog特有的拼接运算符:{}C={a,b[3:0]} //将变量a与变量b的低四位拼接起来,赋值给变量C5、模块Verilog的基本设计单元是“模块”(类似C语言中的函数)一个模块由两部分组成描述接口描述逻辑接口一个模块的示例: module test(LED,a,b,c,d,e); //模块开始的关键字是:module 括号里的都是:端口定义output LED,c,d; //输出信号 input output 都是:IO说明 input a,b; //输入信号reg[7:0] LED; //寄存器数据类型 reg e; //寄存器数据类型 wire f; //线网数据类型 f:内部信号 //变量声明结束后,都是:功能定义 assign c=a|b; assign d=a&b; //assign :产生wire信号语句的关键字 描述组合逻辑 always begin //always:产生reg信号语句的关键字 描述组合、时序逻辑 LED=8'b10101010;end endmodule //模块要用“endmodule”结束 与C语言不同的是,Verilog中多个<always>块都是“并行”的 ,也就是说,两个<always>块可以同时被执行。单个<always>块是中的代码是顺序执行的。 assign相当于连线,一般是将一个变量的值不间断地赋值给另一个变量,就像把这两个变量连在一起,所以习惯性的当做连线用,比如把一个模块的输出给另一个模块当输入。 assign的功能属于组合逻辑的范畴,应用范围可概括为以下三点:持续赋值; 连线; 对wire型变量赋值,wire是线网,相当于实际的连接线,如果要用assign直接连接,就用wire型变量。wire型变量的值随时变化。其实以上三点是相通的。 要更好的把握assign的使用,Verilog中有几个要点需要深入理解和掌握:在Verilog module中的所有过程块(如initial块和always块)、连续赋值语句(如assign语句)和实例引用都是并行的。在同一module中这三者出现的先后顺序没有关系。只有连续赋值语句assign和实例引用语句可以独立于过程块而存在于module的功能定义部分。连续赋值assign语句独立于过程块,所以不能在always过程块中使用assign语句。 module LED_Blink( //可以在端口定义时 指定IOinput sys_clk,//系统时钟inputsys_rst_n, //系统复位output reg[3:0] led;//4bit 代表四颗灯);reg [23:0] count; //计数 (这是一个内部信号声明)//计数器对系统时钟计数,0.2s/*赋值“=”用于阻塞式赋值(执行到该行时,等待赋值完成再执行下一条语句),仿真是initial中用=;“<=”用于非阻塞式赋值中(执行到改行时,不等待赋值完成,直接执行下一条语句),always中用<=*/always @(posedge sys_clk or negedge sys_rst_n)begin//posedge:上升沿触发 negedge:下降沿触发if(!sys_rst_n)count<=24'd0; //对Count1赋23位十进制的0else if(count<24'd1000_0000)count<=count+1'b1;elsecount<=24'b0;end endmodule赋值“=” 用于阻塞式赋值(执行到该行时,等待赋值完成再执行下一条语句),仿真是initial中用=;赋值“<=”用于非阻塞式赋值中(执行到改行时,不等待赋值完成,直接执行下一条语句),always中用<= 6、模块的调用在模块调用时,信号通过模块端口在模块之间传递。module seg_led_static_top( //上层模块input sys_clk,//系统时钟inputsys_rst_n, //系统复位output [5:0] sel; output [7:0] sel_led;);parameter TIME_SHOW=25'd25000_000; //宏定义wireadd_flag;//数码管变化通知 //# 是延迟的意思,井号后面数字是延迟的数量 //#1 a=1;#表延迟,延迟一个时间单位后执行a=1 time_count #( //这里的#表示:用来将parameter变量传给调用实例。.MAX_NUM(TIME_SHOW) //上层模块传输给底层模块)u_time_count(.clk (sys_clk) // .表示:连接 将上层模块的sys_clk与下层模块clk连接在一起.rst_n(sys_rst_n).flag(add_flag)) endmodule module time_count( // 底层模块input clk,//系统时钟inputrst_n, //系统复位output reg flag; );parameter MAX_NUM=25'd50000_000; //宏定义reg [24:0] cnt; endmodule# 是延迟的意思,井号后面数字是延迟的数量 例如代码 : #1 a=1; //延迟一个时间单位后执行a=1#():这里的#表示:用来将parameter变量传给调用实例。.是连接的意思:将上层模块的变量与下层模块变量连接在一起7、结构语言7.1 always 和 initialinitial 语句只执行一次always 语句是一直不断重复的//initial 语句只执行一次//always 语句是一直不断重复的initial beginsys_clk=10;b=11;c=12;#20d=13;end//赋值“=”用于阻塞式赋值(执行到该行时,等待赋值完成再执行下一条语句),仿真是initial中用=; always #10 sys_clk<=~sys_clk; //chans 50Mhz的时钟,周期为20ns//“<=”用于非阻塞式赋值中(执行到改行时,不等待赋值完成,直接执行下一条语句)always中用<= always的时间就控制可以是沿触发,也可以是电平触发。 沿触发的always块常用于表示时序逻辑行为always @(posedge sys_clk or negedge sys_rst_n)begin//posedge:上升沿触发 negedge:下降沿触发if(!sys_rst_n)count<=24'd0; //对Count1赋23位十进制的0else if(count<24'd1000_0000)count<=count+1'b1;elsecount<=24'b0;end or 连接的多个时间或者信号组成的列表称为:敏感列表 只有敏感列表里的条件满足时,才会执行此always模块电平触发的always模块表示组合逻辑行为always @(*)begin out1=a?(b+c):(d+e);end//@(*):模块中所有使用的输入变量都是敏感的 @(*):模块中所有使用的输入变量都是敏感的组合逻辑:输出只取决于输入时序逻辑:输出取决于输入和原电路状态7.2 阻塞赋值和非阻塞赋值 阻塞赋值:只有一个步骤的操作,即执行到该行赋值语句时,要等待赋值完成再执行下一条语句,是一个顺序执行的串行方式。(这点与C语言一致) 假设 a=1,b=2,C=3 执行 a=0;b=a;c=b; 后 a b c的值都为0非阻塞赋值:多个步骤同时的操作,即执行到改行时,不等待赋值完成,直接执行下一条语句,是一个顺序执行的并行方式。 假设 a=0,b=2,C=3 执行 a<=0;b<=a;c<=b; 后 a =0 b=1 c=2 描述组合逻辑的always语句用“阻塞赋值=” 描述时序逻辑的always语句用“非阻塞赋值<=”注意:1.在同一个always模块中不同时使用 非阻塞赋值 和 阻塞赋值 2. 不允许在多个always块中一个变量进行赋值 ,因为Verilog是并行执行的 阻塞赋值和非阻塞赋值产生的实际电路区别: 当存在多条赋值语句时,阻塞赋值会产生多个级联的触发器.7.3 条件语句 if....else if .........else if.......... 用法和C语言相同。 if语句中的条件,为1则表示真,若为0 X Z都按假处理 if else 后面可以用begin 和end包含多个语句,类似与C语言中 if后面的大括号if......esle..........是带有优先级的,实际产生的电路如下: case语句 分支表达式的值互不相同 所有表达式的位宽必须相等(必须定位宽) caseZ不适用于高阻值Z (casez) casex 下列代码 语句1 和语句2 都不执行 case是没有优先级的 实际电路如下: 7.4 循环7.4.1:forever:连续循环执行 一般只用于仿真测试 7.4.2:repeat 执行固定次数循环7.4.3 while循环 while循环与C语言相同,但是Verilog中只用于仿真调试 7.4.4 for循环 与C语言相同,实际产生的是一个多层级的物理电路,for循环在Verilog中比较常用。 7.5 函数 函数通常为一系列组合逻辑,有返回值 函数关键字:function函数定义://下面相当于函数声明function [15:0]mult;//函数名 input[7:0] a,b; reg [15:0] r; integer i; //整数(integer),integer类型的变量为有符号数//下面相当于函数主体 begin if(a[0]==1) r=b; else r=0; for (i =1 ;i<=7 ;i=i+1 ) begin if(a[i]==1) r=r+b<<1; end mult=r; //返回值就是函数名 end endfunction函数调用: module mult_acc( input[7:0] ina,inb; ) wire[15:0]mult_out; assign mult_out=mult(ina,inb);//函数调用endmodule 7.6 任务任务关键字:taskmodule module_name task add_num; //任务定义 input a,b; output c; begin c=a+b; endendtask reg num;add_num(1,2,num) //任务调用 endmodule函数 与任务的区别 function task在时间0开始执行 执行过程中不能暂停不能包含延时、时间、或者其他 时间控制操作可在非0仿真时间执行可包含延时、时间或其他时间控制操作必须包含至少一个输入 可以没有输入、输出不能使用输出/双向参数 (类似C的形参带出返回值),只能返回1个值,返回变量与函数名相同使用输出参数、可以返回多个值函数可以调用另一个函数,但是不能调用任务任务可以调用另外的函数或者任务。 8、状态机(FSM) 状态机:在有限个状态之间按一定规律转换的时序电路 mealy状态机 : 输出与当前状态和输入有关 (时序逻辑的类似) moore状态机: 输出只与输入有关(组合逻辑类似)状态机模型中由 两个组合逻辑 和 一个时序逻辑 组成8.1设计状态机 以下的设计步骤:状态空间定义状态跳转下个状态判断各个状态的动作 8.1.1状态空间定义是一个定义的过程 宏定义出状态的名称 和数值定义当前状态和下一个状态的存储变量(变量要与上面定义的数值位数相同) 推荐每一个状态只有寄存器的一个位置,这样编译逻辑简单,编译后的硬件电路简单 8.1.2状态跳转状态跳转是一个时序逻辑 再次强调:时序逻辑中使用 非阻塞赋值 8.1.3下一个状态的判断根据输入状态判断输出状态,是一个组合逻辑 再次强调:组合逻辑中使用 阻塞赋值 latch:是一个锁存器,程序设计中要避免latch的产生,他会使我们电路输出的信号产生毛刺(if else 没有配对 case中没有default 就会产生latch) 8.1.4下一个状态的动作根据当前状态完成当前动作,是一个组合逻辑下面是产生组合逻辑的两种方式: always:可以表示时序逻辑 和 组合逻辑 mealy状态机 后面又加了一级寄存器来实现时序逻辑的输出,这么做的好处是:可以在有效的滤去组合逻辑输出的毛刺可以有效的进行时序计算和约束对于总线型的输出信号来说,容易使总线对齐,从而减小总线数据见的便宜,减小接收端数据采样的出错频率转自:https://blog.csdn.net/qq_34301282/article/details/120763063
2023年08月29日
6 阅读
0 评论
0 点赞
2023-08-06
ZYNQ lwip 自适应网络速率
默认的网络自动识别接入速率有bug,需做如下修改。找到lwip库文件,libsrc->lwip202->src->contrib->ports->xulinx->netif,打开文件xemacpsif_physpeed.c找到static u32_t get_Realtek_phy_speed(XEmacPs *xemacpsp, u32_t phy_addr),将此函数删除或者注释掉,加入如下函数static u32_t get_Realtek_phy_speed(XEmacPs *xemacpsp, u32_t phy_addr) { u16_t temp; u16_t control; u16_t status; u16_t status_speed; u32_t timeout_counter = 0; xil_printf("Start PHY autonegotiation \r\n"); XEmacPs_PhyWrite(xemacpsp,phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 2); XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, &control); control |= IEEE_RGMII_TXRX_CLOCK_DELAYED_MASK; XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, control); XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0); XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &control); control |= IEEE_ASYMMETRIC_PAUSE_MASK; control |= IEEE_PAUSE_MASK; control |= ADVERTISE_100; control |= ADVERTISE_10; XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, control); XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, &control); control |= ADVERTISE_1000; XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, control); XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0); XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_COPPER_SPECIFIC_CONTROL_REG, &control); control |= (7 << 12); /* max number of gigabit attempts */ control |= (1 << 11); /* enable downshift */ XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_COPPER_SPECIFIC_CONTROL_REG, control); XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control); control |= IEEE_CTRL_AUTONEGOTIATE_ENABLE; control |= IEEE_STAT_AUTONEGOTIATE_RESTART; XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control); XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control); control |= IEEE_CTRL_RESET_MASK; XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control); while (1) { XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control); if (control & IEEE_CTRL_RESET_MASK) continue; else break; } XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status); xil_printf("Waiting for PHY to complete autonegotiation.\r\n"); while ( !(status & IEEE_STAT_AUTONEGOTIATE_COMPLETE) ) { sleep(1); XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_COPPER_SPECIFIC_STATUS_REG_2, &temp); timeout_counter++; if (timeout_counter == 30) { xil_printf("Auto negotiation error \r\n"); return 0; } XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status); } xil_printf("autonegotiation complete \r\n"); XEmacPs_PhyRead(xemacpsp, phy_addr,0x1A, &status_speed); if ( (status_speed & 0x30) == 0x20)/* 1000Mbps */ return 1000; else if ( (status_speed & 0x30) == 0x10)/* 100Mbps */ return 100; else if ( (status_speed & 0x30) == 0x00)/* 10Mbps */ return 10; return XST_FAILURE; }
2023年08月06日
2 阅读
0 评论
0 点赞