FPGA|CPLD|ASICwilliam hill官网
直播中

PCB62304753

6年用户 154经验值
擅长:嵌入式技术
私信 关注

【FPGA开发者项目连载】基于高云FPGA的方波发生器

bandicam 2021-05-15 17-24-15-216

` 本帖最后由 PCB62304753 于 2021-5-15 18:42 编辑

前言FPGA的市场一直在外国的三个巨头的手续牢牢把持,很高兴国内能有高云这样的企业去做,去弥补国内市场的空白,高云这块小蜜蜂fpga内置一个m3的硬核,对于fpga设计是一个很好的补充,很多设计可以利用mcu与fpga互为补充进行设计。因为平时没啥时间,还想尽可能的去体验一下高云的MCU硬核,所以设计了这样一个题目,按照架构也可以很容易的做一个任意信号发生器,有时间可以继续完善一下,当然这是后话了。之前只是简单的使用过altera的一款芯片,开发经验不足,望大家多多指教。

设计思路
整个设计包含如下几个部分:
1.方波输出
2.按键输入
3.oled显示
这里我把它分为两个部分。FPGA部分驱动方波生成,MCU部分驱动按键与oled显示。两者直接通过AHB总线进行通信
流程为:oled显示当前频率,当监测到有按键操作的时候去处理按键,同时通过AHB总线将设置的频率发送给fpga部分。

MCU程序设计
这里用0xA0000000地址去存放需要发给fpag的频率(此处的数据是按照32位溢出以及27MHz时钟转换出来的累加值),
1.判断三个按键状态。当按键按下时,先消抖,然后等待按键抬起。按键功能分别是:移动光标,减少光标所在处频率的数值,增加光标所在处频率的数值。
2.把转换完的频率写入0xA0000000地址(转换式为频率*2^32/27000000)。
3.修改屏幕上的显示。
  1. uint32_t freq = 0; //频率
  2. uint8_t place = 0; //选中

  3. SystemInit();
  4. GPIOInit();

  5. OLED_Init();                        //初始化OLED  
  6. OLED_Clear();

  7. while(1)
  8. {
  9.         if((GPIO_ReadBits(GPIO0)&GPIO_Pin_2) == 0)
  10.         {
  11.                 delay_ms(20);
  12.                 while((GPIO_ReadBits(GPIO0)&GPIO_Pin_2) == 0){}
  13.                
  14.                 freq += reduce_freq[place];
  15.       
  16.         }
  17.         if((GPIO_ReadBits(GPIO0)&GPIO_Pin_3) == 0)
  18.         {
  19.                 delay_ms(20);
  20.                 while((GPIO_ReadBits(GPIO0)&GPIO_Pin_3) == 0){}
  21.                 if(freq > reduce_freq[place])
  22.                         freq -= reduce_freq[place];
  23.                 else
  24.                         freq = 0;
  25.       
  26.         }
  27.         if((GPIO_ReadBits(GPIO0)&GPIO_Pin_4) == 0)
  28.         {
  29.                 delay_ms(20);
  30.                 while((GPIO_ReadBits(GPIO0)&GPIO_Pin_4) == 0);
  31.                
  32.                 place++;
  33.                 if(place > 7)
  34.                         place = 0;
  35.         }
  36.       
  37.         *((uint32_t *)0xA0000000) = freq*159.0728628148148148;  //把频率给fpga

  38.         {
  39.                 OLED_ShowChar(16+8*0, 3, '0'+freq/10000000%10, place==7?1:0);
  40.                 OLED_ShowChar(16+8*1, 3, '0'+freq/1000000%10, place==6?1:0);
  41.                 OLED_ShowChar(16+8*2, 3, ',',0);
  42.                 OLED_ShowChar(16+8*3, 3, '0'+freq/100000%10, place==5?1:0);
  43.                 OLED_ShowChar(16+8*4, 3, '0'+freq/10000%10, place==4?1:0);
  44.                 OLED_ShowChar(16+8*5, 3, '0'+freq/1000%10, place==3?1:0);
  45.                 OLED_ShowChar(16+8*6, 3, ',',0);
  46.                 OLED_ShowChar(16+8*7, 3, '0'+freq/100%10, place==2?1:0);
  47.                 OLED_ShowChar(16+8*8, 3, '0'+freq/10%10, place==1?1:0);
  48.                 OLED_ShowChar(16+8*9, 3, '0'+freq/1%10, place==0?1:0);
  49.                 OLED_ShowChar(16+8*10, 3 ,'H',0);
  50.                 OLED_ShowChar(16+8*11, 3 ,'z',0);
  51.         }
  52. }

FPGA程序设计
分为top、硬核、AHB解析、方波发生。
top:主要是实例化各个模块。
硬核部分:使用了gpio与AHB2 Master两部分,ip核,使用软件配置起来非常方便。
QQ截图20210515172707.png
AHB解析部分:在AHB的0位置处,设计了一个reg_freq寄存器,为32位,用于接收MCU发来的方波的频率。
  1. `timescale 100 ps/100 ps

  2. module Gowin_AHB_Multiple
  3. (
  4. output [31:0] freq,
  5.         output        wire        [31:0]        AHB_HRDATA,
  6.         output        wire                        AHB_HREADY,
  7.         output        wire        [ 1:0]        AHB_HRESP,
  8.         input        wire        [ 1:0]  AHB_HTRANS,
  9.         input        wire        [ 2:0]  AHB_HBURST,
  10.         input        wire        [ 3:0]  AHB_HPROT,
  11.         input        wire        [ 2:0]        AHB_HSIZE,
  12.         input        wire                        AHB_HWRITE,
  13.         input        wire                        AHB_HMASTLOCK,
  14.         input        wire        [ 3:0]        AHB_HMASTER,
  15.         input        wire        [31:0]        AHB_HADDR,
  16.         input        wire        [31:0]  AHB_HWDATA,
  17.         input        wire                        AHB_HSEL,
  18.         input        wire                        AHB_HCLK,
  19.         input        wire                        AHB_HRESETn
  20. );

  21. //The AHB BUS is always ready
  22. assign AHB_HREADY = 1'b1; //ready signal, slave to MCU master
  23. //Response OKAY
  24. assign AHB_HRESP  = 2'b0;//response signal, slave to MCU master

  25. //Define Reg for AHB BUS
  26. reg [31:0]  ahb_address;
  27. reg                 ahb_control;
  28. reg         ahb_sel;
  29. reg         ahb_htrans;

  30. always @(posedge AHB_HCLK or negedge AHB_HRESETn)
  31. begin
  32.         if(~AHB_HRESETn)
  33.         begin
  34.                 ahb_address  <= 32'b0;
  35.                 ahb_control  <= 1'b0;
  36.         ahb_sel      <= 1'b0;
  37.         ahb_htrans   <= 1'b0;
  38.         end
  39.         else              //Select The AHB Device
  40.         begin                          //Get the Address of reg
  41.                 ahb_address  <= AHB_HADDR;
  42.                 ahb_control  <= AHB_HWRITE;
  43.         ahb_sel      <= AHB_HSEL;
  44.         ahb_htrans   <= AHB_HTRANS[1];
  45.         end
  46. end

  47. wire write_enable = ahb_htrans & ahb_control    & ahb_sel;
  48. wire read_enable  = ahb_htrans & (!ahb_control) & ahb_sel;

  49. //The register of Multiple AHB bus
  50. reg [32:0] reg_freq;

  51. //write data to AHB bus
  52. always @(posedge AHB_HCLK or negedge AHB_HRESETn)
  53. begin
  54.         if(~AHB_HRESETn)
  55.         begin
  56.                  reg_freq   <= 32'b0;
  57.         end
  58.         else if(write_enable)
  59.         begin
  60.                 case (ahb_address[15:0])
  61.                 16'h0000: reg_freq         <= AHB_HWDATA[31:0];
  62.                 endcase
  63.         end
  64. end

  65. //register address
  66. reg [31:0] ahb_rdata;

  67. always @(*)
  68. begin
  69.         if(read_enable)  //read cmd
  70.         begin
  71.                 case (ahb_address[15:0])
  72.                 32'h0000:  ahb_rdata = reg_freq;
  73.                 default:ahb_rdata = 32'hFFFFFFFF;
  74.                 endcase
  75.         end
  76.     else
  77.     begin
  78.         ahb_rdata = 32'hFFFFFFFF;
  79.     end
  80. end

  81. assign AHB_HRDATA = ahb_rdata;

  82. assign freq = reg_freq;
  83.         
  84. endmodule
方波发生部分:就是一个32位累加器,通过修改单次累加数据的大小来控制波形的周期
  1. module wave (
  2.     input sys_clk,
  3.     input reset_n,
  4.     input [31:0] freq,
  5.     output wave_out
  6. );

  7. reg [31:0] phase_acc;
  8. always @(posedge sys_clk) phase_acc <= phase_acc + freq;
  9. wire [31:0] phase = phase_acc;
  10. assign wave_out = phase[31];  

  11. endmodule

芯片资源的使用
MCU部分:
  1. ==============================================================================


  2.       Code (inc. data)   RO Data    RW Data    ZI Data      Debug   

  3.       2880        142       2324         16       1632      38415   Grand Totals
  4.       2880        142       2324         16       1632      38415   ELF Image Totals
  5.       2880        142       2324         16          0          0   ROM Totals

  6. ==============================================================================

  7.     Total RO  Size (Code + RO Data)                 5204 (   5.08kB)
  8.     Total RW  Size (RW Data + ZI Data)              1648 (   1.61kB)
  9.     Total ROM Size (Code + RO Data + RW Data)       5220 (   5.10kB)

  10. ==============================================================================
FPGA部分:
QQ截图20210515182629.png

实物图片


结语:尝试了高云这种内置MCU的FPGA,我觉得开发起来确实是方便很多,不过硬核自带的很多外设ip给人一种不是太完善的感觉,不过想想也是,这个混合式的芯片,硬核的外设ip多半是用户定制开发的。不过还是希望官方能提供更多更优质的ip供用户选择。

附录
mcu_project.zip (78.12 KB)
(下载次数: 3, 2021-5-15 18:38 上传)
fpga_project.zip (303.83 KB)
(下载次数: 4, 2021-5-15 18:38 上传)

` QQ截图20210515182745.png

更多回帖

发帖
×
20
完善资料,
赚取积分