回答

收藏

[评测分享] 【ALINX&紫光同创PGL12G开发板】-2-对VerilogHDL代码的入门理解

#板卡评测 #板卡评测 3024 人阅读 | 0 人回复 | 2020-08-25

本帖最后由 独活草 于 2020-8-25 15:32 编辑

  大概花了2天,静下心来去尝试理解PGL12G开发板官方提供的前三个实验的VerilogHDL代码,同时结合下载程序后板子的实际运行效果,尝试调整参数验证猜测;竟然取得一点成果,现将代码全注释给大家分享一下:***************************************************************************************************
实验1:流水灯
`timescale 1ns / 1ps   //一般用在VerilogHDL编程最开始声明的地方,意思单位时间为1ns,精度为1ps
                   //如果后面要用到延时,#d 可以直接调用这个时间:#3就是延时3ns的意思
module led_test
(            
  sys_clk,        // 系统时钟50Mhz
  rst_n,         //复位按钮,低电平有效           
  led           // LED状态寄存器
);
//输入输出端口申明
input        sys_clk;
input        rst_n;
output [3:0]    led;
reg [31:0]      timer; //定义32位的计数器
reg [3:0]       led;  //定义4位LED状态寄存器
//0~ 49_999_999 1秒
//0~ 99_999_999 2秒
//0~149_999_999 3秒
//0~199_999_999 4秒

always@(posedge sys_clk or negedge rst_n) //每个时钟周期或者复位信号产生时
begin
    if (~rst_n)//复位按钮松开时是高电平,按下时是低电平,此处取反
        timer <= 32'd0;//复位时,把32位计数器清0
    else if (timer == 32'd199_999_999)
          timer <= 32'd0;//计数到第四秒,把32位计数器清0,重新计数
    else
          timer <= timer + 1'b1;//计数器做 +1 运算;
end

// LED control
always@(posedge sys_clk or negedge rst_n) //每个时钟周期或者复位信号产生时
begin
    if (~rst_n)
        led <= 4'b0000;//复位时,把4个LED置为低电平,点亮4个LED灯
    else if (timer == 32'd49_999_999)
        led <= 4'b0001; //计数到第1秒时,LED1熄灭;
    else if (timer == 32'd99_999_999)
        led <= 4'b0010; //计数到第2秒时,LED2熄灭;
    else if (timer == 32'd149_999_999)
        led <= 4'b0100; //计数到第3秒时,LED3熄灭;
    else if (timer == 32'd199_999_999)
        led <= 4'b1000;//计数到第4秒时,LED4熄灭;
end
endmodule
***************************************************************************************************
实验2:按键
module key_test
(
input            sys_clk,         //系统时钟 50Mhz
input [3:0]        key_in,         //按健,按下时为低电平,松开时高电平,默认为高电平
output[3:0]        led            //LED 低电平时点亮
);                     
reg[3:0] led_r;          //定义第1阶段D锁存器
reg[3:0] led_r1;         //定义第2阶段D锁存器
always@(posedge sys_clk )//每个时钟周期
begin     
    led_r <= ~key_in;     //第1阶段锁存数据
end                        
always@(posedge sys_clk )
begin
    led_r1 <= led_r;      //第2阶段锁存数据
end
assign led = led_r1;   //assign表示连续赋值,且被赋值的变量只能是wire型的
endmodule

//wire 表示直通,只要输入有变化,输出马上无条件地反映;reg 表示一定要有触发,输出才会响应输入
//reg 型变量,赋值只能在always块内部赋值;
//wire 使用在连续赋值语句中,reg使用在过程赋值语句中;默认类型
//wire 只能被assign连续赋值,reg只能在initial和always块内部赋值;
***************************************************************************************************
将实验2的代码改为下面可以实现同样的效果:
module key_test
(
input               sys_clk,      
input [3:0]           key_in,      
output[3:0]           led        
);
assign led = ~key_in; //赋值                                                
endmodule
***************************************************************************************************
实验3:PLL
module pll_test
(
input      sys_clk,                    //系统时钟50Mhz
input      rst_n,                      //复位按钮,低电平有效         
output     clk_out                     //倍频或分频 输出的时钟信号 J9_Pin3
);
wire      locked;    //wire表示直通,只要输入有变化,输出马上无条件地反映

/////////////////////PLL IP 核调用////////////////////////////
clk_wiz_0 clk_wiz_0_inst         //实例化clk_wiz_0
.clkin1    (sys_clk),          // 50Mhz系统时钟导入
// 时钟信号输出端口
.clkout0    (      ),         // OUT 200Mhz
.clkout1    (      ),         // OUT 100Mhz
.clkout2    (      ),         // OUT 50Mhz
.clkout3    (clk_out  ),         // OUT 25Mhz         
//控制信号         
.pll_rst    (~rst_n  ),         // 复位
.pll_lock   (locked  )             // 锁住频率
);               
endmodule
***************************************************************************************************
  通过最近两天的学习,我大概理解 VerilogHDL 语言编程的目的是为了对一个具有输入输出的黑箱,其要实现某个运算目的而进行逻辑设计;
1、编程风格大概是先在 module 中申明定义好要用到的资源:输入、输出、IP核、中间变量(寄存器等);
2、然后编写在每个时钟周期或者复位信号产生时//always@(posedge sys_clk or negedge rst_n) 要进行的初始化或其他赋值操作;
3、实现运算的逻辑结构简单,常用的就是if-else;case(类似switch-case);
4、调用开发环境平台具有的一些IP核,需要多花时间去研究哪些私有变量是一定要赋值的。









分享到:
回复

使用道具 举报

您需要登录后才可以回帖 注册/登录

本版积分规则

关闭

站长推荐上一条 /3 下一条