Программа Led Counter (0 - 15) с разными частотами

Я хочу сделать счетчик с 4 светодиодами на плате Zybo, который рассчитывает от 0 до 15. Также я хочу, чтобы 4 кнопки платы соответствовали разной частоте для смены светодиодов (0,5 Гц, 1 Гц, 2 Гц, 4 Гц). Я уже достиг простого счетчика с фиксированной частотой, но не второй части с частотой изменения кнопки.

В блочном дизайне у меня есть система обработки Zynq, AXI GPIO, которая считывает данные кнопок и пользовательский 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), который, в свою очередь, отправляет их в reg0 в модуле Clock_Divider.

Основная программа 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, потому что при их нажатии в терминале печатаются правильные строки. Но когда я нажимаю кнопки, частота не меняется. Кроме того, он работает с очень медленной частотой, намного медленнее, чем 1 Гц, которая должна быть по умолчанию, даже если данные кнопки не отправляются на пользовательский IP-адрес.

Проблема должна лежать где-то либо в логике регистра reg0 в пользовательском IP-адресе, либо в отправке данных кнопки из процессора в регистр пользовательского IP-адреса.

1 ответ

Решение

Я внес изменения, предложенные 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);
    }

потому что после нескольких тактов ни одна кнопка не будет нажата, и она отправит сигнал 0000 в slv_reg0.

Другие вопросы по тегам