2016-05-10 2 views
0

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

В блочном дизайне у меня есть Zynq Processing System, 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.

программа Main 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

В Verilog '0010' десять, а не двоичные два. Я думаю, вы хотите '4'b0010' – Greg

+0

Я изменил его, и все же он работает с очень низкой частотой. Но даже с прежними значениями не должно быть постоянным, но всегда стоит значение 50000000, а счетчик работает на частоте 1 Гц? – vic

+0

Проблема, которая сохраняется после многих попыток, заключается в том, что даже если данные кнопки не передаются на логику делителя тактового сигнала, constantNumber должен быть 50000000, а счетчик должен работать на частоте 1 Гц, независимо от нажатых кнопок. Но теперь он работает очень медленно, когда светодиоды меняют ситуацию примерно каждые 85 секунд. – vic

ответ

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.

+0

Все ли изменения повлияли на вашу проблему? Вы также изменили 'count == constantNumber - 1' на' count> = constantNumber - 1', чтобы удалить риск того, что 'constantNumber' изменится на значение ниже' count'? – Greg

+0

Да, я включил изменения, которые вы предложили. – vic

Смежные вопросы