2016-05-10 74 views
0

我想用一個Zybo板上的4個LED指示計數從0到15的計數器。另外我希望板的4個按鍵對應不同的頻率用於改變LED(0.5Hz,1Hz,2Hz,4Hz)。我已經實現了固定頻率的簡單計數器,但沒有按鈕頻率改變的第二部分。不同頻率的LED計數器編程(0 - 15)

在模塊設計中,我有一個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),其反過來將它們發送到所述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讀因爲當按下他們正確的線在終端打印。但是當我按下按鈕時,頻率不會改變。此外,它的運行頻率非常慢,比即使按鈕數據未發送到自定義IP時默認值爲1Hz的頻率慢得多。

問題必須存在於自定義IP中的reg0案例邏輯或從cpu發送到自定義IP的寄存器的按鈕數據的某處。

+1

在Verilog'0010'中是十個,而不是二進制二。我想你想'4'b0010' – Greg

+0

我改變了它,仍然以非常低的頻率運行。但即使與前值不應該constantNumber總是採取值50000000和計數器運行在1Hz? – vic

+0

許多嘗試後仍然存在的問題是,即使按鈕數據沒有傳輸到時鐘分頻器邏輯,constantNumber也應該是50000000,並且無論按下哪個按鈕,計數器都應以1Hz運行。但現在它運行非常緩慢,LED每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