不同频率的 LED 计数器程序 (0 - 15)
Led Counter Program (0 - 15) with different frequencies
我想用 Zybo 板上的 4 个 LED 做一个计数器,从 0 到 15。我还希望板上的 4 个按钮对应于 LED 变化的不同频率(0.5Hz , 1赫兹, 2赫兹, 4赫兹)。我已经实现了固定频率的简单计数器,但不是按钮频率变化的第二部分。
在块设计中,我有一个 Zynq 处理系统、一个读取按钮数据的 AXI GPIO 和一个用作 LED 驱动器、时钟分频器和变频器的自定义 IP。
自定义IP
时钟分频器模块代码。
module Clock_Divider(
input clk,
input rst,
input reg0,
output reg clk_out
);
reg [31:0] count;
reg constantNumber;
always @ (reg0)
begin
if(reg0 == 0000)
constantNumber = 50000000;
else if(reg0 == 0001)
constantNumber = 100000000;
else if(reg0 == 0010)
constantNumber = 50000000;
else if(reg0 == 0100)
constantNumber = 25000000;
else if(reg0 == 1000)
constantNumber = 12500000;
else
constantNumber = 50000000;
end
always @ (posedge(clk), posedge(rst))
begin
if (rst == 1'b1)
begin
count <= 32'b0;
end
else if (count == constantNumber - 1)
begin
count <= 32'b0;
end
else
begin
count <= count + 1;
end
end
always @ (posedge(clk), posedge(rst))
begin
if (rst == 1'b1)
clk_out <= 1'b0;
else if (count == constantNumber - 1)
clk_out <= ~clk_out;
else
clk_out <= clk_out;
end
endmodule
寄存器constantNumber取对应的值,以改变时钟频率
自定义 IP 逻辑的其余部分。
Clock_Divider UIP (.clk(S_AXI_ACLK), .rst(), .reg0(slv_reg0), .clk_out(clk_out));
reg [3:0] counter = 0;
always @(posedge clk_out)
begin
if(counter < PWM_COUNTER_MAX-1)
begin
counter <= counter + 1;
end
else
counter <= 0;
end
assign PWM0 = counter[0];
assign PWM1 = counter[1];
assign PWM2 = counter[2];
assign PWM3 = counter[3];
按钮数据被发送到自定义 IP (slv_reg0) 的第一个寄存器,后者又将它们发送到 Clock_Divider 模块中的 reg0。
主要C程序
#include <stdio.h>
#include "platform.h"
#include <xgpio.h>
#include "xparameters.h"
#include "sleep.h"
#include "xil_io.h"
//#define MY_PWM XPAR_MY_PWM_CORE_0_S00_AXI_BASEADDR //Because of a bug in Vivado 2015.3 and 2015.4, this value is not correct.
#define MY_PWM 0x43C00000 //This value is found in the Address editor tab in Vivado (next to Diagram tab)
int main(){
XGpio input;
int button_data = 0;
XGpio_Initialize(&input, XPAR_AXI_GPIO_0_DEVICE_ID); //initialize input XGpio variable
XGpio_SetDataDirection(&input, 1, 0xF); //set first channel tristate buffer to input
init_platform();
while(1){
button_data = XGpio_DiscreteRead(&input, 1); //get button data
if(button_data == 0b0000){
Xil_Out32(MY_PWM, button_data);
}
else if(button_data == 0b0001){
xil_printf("button 0 pressed\n\r");
Xil_Out32(MY_PWM, button_data);
}
else if(button_data == 0b0010){
xil_printf("button 1 pressed\n\r");
Xil_Out32((MY_PWM), button_data);
}
else if(button_data == 0b0100){
xil_printf("button 2 pressed\n\r");
Xil_Out32((MY_PWM), button_data);
}
else if(button_data == 0b1000){
xil_printf("button 3 pressed\n\r");
Xil_Out32((MY_PWM), button_data);
}
else{
xil_printf("multiple buttons pressed\n\r");
Xil_Out32(MY_PWM, 0b0000);
}
}
cleanup_platform();
return 0;
}
我可以确认 AXI GPIO 正确读取了按钮数据,因为按下它们时终端中会打印正确的行。但是当我按下按钮时,频率并没有改变。它还以非常慢的频率运行,比默认的 1Hz 慢得多,即使按钮数据没有发送到自定义 IP。
问题必须出在自定义 IP 中的 reg0 案例逻辑或按钮数据从 cpu 发送到自定义 IP 的寄存器的某个地方。
我进行了 Greg 提议的更改以及我自己的一些更改,我终于让它工作了。
在时钟分频器文件中,我做了以下更改。
input [3:0] reg0,
reg [31:0] constantNumber;
always @ (reg0)
begin
if(reg0 == 4'b0000)
constantNumber = 50000000;
else if(reg0 == 4'b0001)
constantNumber = 100000000;
else if(reg0 == 4'b0010)
constantNumber = 50000000;
else if(reg0 == 4'b0100)
constantNumber = 25000000;
else if(reg0 == 4'b1000)
constantNumber = 12500000;
else
constantNumber = 50000000;
end
我将 consantNumber 设置为 32 位以确保没有溢出。
在自定义 IP 逻辑中,我更改了 reg0 的参数,以便将 slv_reg0 的正确(最后)位发送给它。
Clock_Divider UIP (.clk(S_AXI_ACLK), .rst(), .reg0(slv_reg0[3:0]), .clk_out(clk_out));
最后但同样重要的是 c 程序的变化。
if(button_data == 0b0001){
xil_printf("button 0 pressed\n\r");
Xil_Out32(MY_PWM, 0b0001);
}
else if(button_data == 0b0010){
xil_printf("button 1 pressed\n\r");
Xil_Out32((MY_PWM), 0b0010);
}
else if(button_data == 0b0100){
xil_printf("button 2 pressed\n\r");
Xil_Out32((MY_PWM), 0b0100);
}
else if(button_data == 0b1000){
xil_printf("button 3 pressed\n\r");
Xil_Out32((MY_PWM), 0b1000);
}
else if(button_data > 0b0000){
xil_printf("button 3 pressed\n\r");
Xil_Out32((MY_PWM), 0b0000);
}
我摆脱了:
if(button_data == 0b0000){
Xil_Out32(MY_PWM, button_data);
}
因为在几个时钟滴答声后没有按下任何按钮,它会向 slv_reg0 发送 0000 信号。
我想用 Zybo 板上的 4 个 LED 做一个计数器,从 0 到 15。我还希望板上的 4 个按钮对应于 LED 变化的不同频率(0.5Hz , 1赫兹, 2赫兹, 4赫兹)。我已经实现了固定频率的简单计数器,但不是按钮频率变化的第二部分。
在块设计中,我有一个 Zynq 处理系统、一个读取按钮数据的 AXI GPIO 和一个用作 LED 驱动器、时钟分频器和变频器的自定义 IP。
自定义IP
时钟分频器模块代码。
module Clock_Divider(
input clk,
input rst,
input reg0,
output reg clk_out
);
reg [31:0] count;
reg constantNumber;
always @ (reg0)
begin
if(reg0 == 0000)
constantNumber = 50000000;
else if(reg0 == 0001)
constantNumber = 100000000;
else if(reg0 == 0010)
constantNumber = 50000000;
else if(reg0 == 0100)
constantNumber = 25000000;
else if(reg0 == 1000)
constantNumber = 12500000;
else
constantNumber = 50000000;
end
always @ (posedge(clk), posedge(rst))
begin
if (rst == 1'b1)
begin
count <= 32'b0;
end
else if (count == constantNumber - 1)
begin
count <= 32'b0;
end
else
begin
count <= count + 1;
end
end
always @ (posedge(clk), posedge(rst))
begin
if (rst == 1'b1)
clk_out <= 1'b0;
else if (count == constantNumber - 1)
clk_out <= ~clk_out;
else
clk_out <= clk_out;
end
endmodule
寄存器constantNumber取对应的值,以改变时钟频率
自定义 IP 逻辑的其余部分。
Clock_Divider UIP (.clk(S_AXI_ACLK), .rst(), .reg0(slv_reg0), .clk_out(clk_out));
reg [3:0] counter = 0;
always @(posedge clk_out)
begin
if(counter < PWM_COUNTER_MAX-1)
begin
counter <= counter + 1;
end
else
counter <= 0;
end
assign PWM0 = counter[0];
assign PWM1 = counter[1];
assign PWM2 = counter[2];
assign PWM3 = counter[3];
按钮数据被发送到自定义 IP (slv_reg0) 的第一个寄存器,后者又将它们发送到 Clock_Divider 模块中的 reg0。
主要C程序
#include <stdio.h>
#include "platform.h"
#include <xgpio.h>
#include "xparameters.h"
#include "sleep.h"
#include "xil_io.h"
//#define MY_PWM XPAR_MY_PWM_CORE_0_S00_AXI_BASEADDR //Because of a bug in Vivado 2015.3 and 2015.4, this value is not correct.
#define MY_PWM 0x43C00000 //This value is found in the Address editor tab in Vivado (next to Diagram tab)
int main(){
XGpio input;
int button_data = 0;
XGpio_Initialize(&input, XPAR_AXI_GPIO_0_DEVICE_ID); //initialize input XGpio variable
XGpio_SetDataDirection(&input, 1, 0xF); //set first channel tristate buffer to input
init_platform();
while(1){
button_data = XGpio_DiscreteRead(&input, 1); //get button data
if(button_data == 0b0000){
Xil_Out32(MY_PWM, button_data);
}
else if(button_data == 0b0001){
xil_printf("button 0 pressed\n\r");
Xil_Out32(MY_PWM, button_data);
}
else if(button_data == 0b0010){
xil_printf("button 1 pressed\n\r");
Xil_Out32((MY_PWM), button_data);
}
else if(button_data == 0b0100){
xil_printf("button 2 pressed\n\r");
Xil_Out32((MY_PWM), button_data);
}
else if(button_data == 0b1000){
xil_printf("button 3 pressed\n\r");
Xil_Out32((MY_PWM), button_data);
}
else{
xil_printf("multiple buttons pressed\n\r");
Xil_Out32(MY_PWM, 0b0000);
}
}
cleanup_platform();
return 0;
}
我可以确认 AXI GPIO 正确读取了按钮数据,因为按下它们时终端中会打印正确的行。但是当我按下按钮时,频率并没有改变。它还以非常慢的频率运行,比默认的 1Hz 慢得多,即使按钮数据没有发送到自定义 IP。
问题必须出在自定义 IP 中的 reg0 案例逻辑或按钮数据从 cpu 发送到自定义 IP 的寄存器的某个地方。
我进行了 Greg 提议的更改以及我自己的一些更改,我终于让它工作了。
在时钟分频器文件中,我做了以下更改。
input [3:0] reg0,
reg [31:0] constantNumber;
always @ (reg0)
begin
if(reg0 == 4'b0000)
constantNumber = 50000000;
else if(reg0 == 4'b0001)
constantNumber = 100000000;
else if(reg0 == 4'b0010)
constantNumber = 50000000;
else if(reg0 == 4'b0100)
constantNumber = 25000000;
else if(reg0 == 4'b1000)
constantNumber = 12500000;
else
constantNumber = 50000000;
end
我将 consantNumber 设置为 32 位以确保没有溢出。
在自定义 IP 逻辑中,我更改了 reg0 的参数,以便将 slv_reg0 的正确(最后)位发送给它。
Clock_Divider UIP (.clk(S_AXI_ACLK), .rst(), .reg0(slv_reg0[3:0]), .clk_out(clk_out));
最后但同样重要的是 c 程序的变化。
if(button_data == 0b0001){
xil_printf("button 0 pressed\n\r");
Xil_Out32(MY_PWM, 0b0001);
}
else if(button_data == 0b0010){
xil_printf("button 1 pressed\n\r");
Xil_Out32((MY_PWM), 0b0010);
}
else if(button_data == 0b0100){
xil_printf("button 2 pressed\n\r");
Xil_Out32((MY_PWM), 0b0100);
}
else if(button_data == 0b1000){
xil_printf("button 3 pressed\n\r");
Xil_Out32((MY_PWM), 0b1000);
}
else if(button_data > 0b0000){
xil_printf("button 3 pressed\n\r");
Xil_Out32((MY_PWM), 0b0000);
}
我摆脱了:
if(button_data == 0b0000){
Xil_Out32(MY_PWM, button_data);
}
因为在几个时钟滴答声后没有按下任何按钮,它会向 slv_reg0 发送 0000 信号。