朱工

早年从事单片机、实时控制系统产品设计及编程。目前耄耋之年开始学习AI技术。

如何用PSoC UDB实现硬件PDM

0
阅读(7163)

如何用PSoC UDB实现硬件PDM

- 基于累加的PDM算法(4)

  除了FPGA/CPLD外,目前能在MCU内部实现基于累加的PDM算法的硬件PDM还只有Cypress PSoC的UDB(PSoC3-5,而PSoC1不带UDB)。本节具体介绍如何用PSoC的UDB Datapath来做基于累加算法的硬件PDM。同时这对熟悉UDB中的Datapath也有好处,因为我觉得UDB的Datapath是一项很有利用价值的资源。

  开发环境为Cypress PSoC Creator 2.2,实例在最近大家都感兴趣的PSoC4上实现。

图0

  我们用 File – New – Project – Empty PSoC4(CY8C42*) Design 建立项目ExampleHWPDM8后(图0),由于我们还没有PDM这个部件(Component),所以还无法画出电路图。因此必须先建立PDM这个部件,步骤如下。

(1)点垂直方向的“Components”TAB,然后右键点Project ExampleHWPDM8,选择“Add Component Item”(图1)。

图1

(2)在弹出的“Add Component Item”窗口,选择“Symbol Wizard”,并在Component Name处填上部件名称(例如)“MyPDM8B”。然后点“Create New”。(图2)

图2

(3)在弹出的“Symbol Creation Wizard”窗口,填写部件的输入、输出端。

  这里输入端为clock – Digital Input。输出端为极性相反的两个输出PDM_p、PDM_n – Digital Output。“Symbol Creation Wizard”窗口会自动生成部件的电路符号。点击“OK”完成此步操作。(图3A)

图3A

  于是项目就有了可供调用的部件“MyPDM8B”的电路符号,其通用名称为“MyPDM8B_N”。将来多个同样的部件可用MyPDM8B_1、MyPDM8B_2、MyPDM8B_3区分。(图3B)

图3B

(4)点“MyPDM8B_N”图纸的空白处右键),并选择“Generate Verilog” (图4),在弹出窗口中点击“Generate”,自动生成Verilog文件“MyPDM8B.v”。

图4

(5)开发环境的主窗口自动显示Verilog文件“MyPDM8B.v”的内容,待编辑(图5A)。新生成的MyPDM8B.v未被保存,要先保存

图5A

  编辑的第一步使用Cypress PSoC Creator 2.2 开发环境提供的Datapath Config Tool完成部件“MyPDM8B”的内部结构配置。

  在开发环境左边窗口用右键点文件“MyPDM8B.v”,在弹出的小窗口选“Datapath Config Tool…”(图5B)。

图5B

(6)自动转到Datapath Config Tool环境。

  根据前面文章的介绍,我们的算法只使用“A0 = A0 + D0”一条指令,所以填写表格非常方便。

(6A)Edit – New Datapath

  本例为8位PDM,所以取Instance Name为PDM8,选Instance Type为cy_psoc3_dp8。点“OK” (图6A)。

图6A

(6B)填写表格:我们只须把CFGRAM – Reg0的FUNC设为“ADD”,以及将ALU结果写回A0(A0 WR SRC 设为 ALU)就可以了,其余都与Default的设置一致,无需改动。(图6B)

图6B

  File – Save会自动写入MyPDM8B.v。然后File – Exit退出Tool环境,回到开发环境。这时开发环境主窗口中的MyPDM8B.v已加入了Datapath Config Tool所添加的Datapath Config内容。(图6C)

图6C

(7)人工编辑MyPDM8B.v。主要是连接Datapath的输入(将时钟clock连至clk)、输出(将加法的进位位co_msb输出至PDM_p及PDM_n);以及加一些注释。(图7A,图7B)。

图7A

图7B

  修改完成的MyPDM8B.v如下:

MyPDM8B.v

//`#start header` -- edit after this line, do not edit this line
// ========================================
//
// Copyright FY_ZHU, 2013
// All Rights Reserved
// UNPUBLISHED, LICENSED SOFTWARE.
//
// CONFIDENTIAL AND PROPRIETARY INFORMATION
// WHICH IS THE PROPERTY OF FY_ZHU.
//
// *The PDM Algorithm Based On Addition :
// *	 CNT += H ;
// * if ( CNT >= N )
// *    { CNT %= N ;  Pout = 1 ; }
// * else Pout = 0 ;
// *This algorithm generates H active output pulses in period N .
// *
// *The algorithm is free for all under mentioning that the algorithm is from author FY_ZHU.
// *
// *In this example the algorithm is implemented using hardware and software respectively.
// *Here the PDM output is generated by hardware, a datapath with only one operation : A0 = A0 + D0 .
//
// ========================================
`include "cypress.v"
//`#end` -- edit above this line, do not edit this line
// Generated on 08/12/2013 at 16:52
// Component: MyPDM8B
module MyPDM8B (
	output  PDM_n,
	output  PDM_p,
	input   clock
);

//`#start body` -- edit after this line, do not edit this line

	/* Connections from the DP */
	wire co_msb;	/* Carry out of MSB */

	/*    c0_msb(Carry out of MSB) to the output - pos/neg    */
	assign PDM_p = co_msb;
	assign PDM_n = ~co_msb;

cy_psoc3_dp8 #(.cy_dpconfig_a(
{
    `CS_ALU_OP__ADD, `CS_SRCA_A0, `CS_SRCB_D0,
    `CS_SHFT_OP_PASS, `CS_A0_SRC__ALU, `CS_A1_SRC_NONE,
    `CS_FEEDBACK_DSBL, `CS_CI_SEL_CFGA, `CS_SI_SEL_CFGA,
    `CS_CMP_SEL_CFGA, /*CFGRAM0:  A0 = A0 + D0*/
    `CS_ALU_OP_PASS, `CS_SRCA_A0, `CS_SRCB_D0,
    `CS_SHFT_OP_PASS, `CS_A0_SRC_NONE, `CS_A1_SRC_NONE,
    `CS_FEEDBACK_DSBL, `CS_CI_SEL_CFGA, `CS_SI_SEL_CFGA,
    `CS_CMP_SEL_CFGA, /*CFGRAM1:  */
    `CS_ALU_OP_PASS, `CS_SRCA_A0, `CS_SRCB_D0,
    `CS_SHFT_OP_PASS, `CS_A0_SRC_NONE, `CS_A1_SRC_NONE,
    `CS_FEEDBACK_DSBL, `CS_CI_SEL_CFGA, `CS_SI_SEL_CFGA,
    `CS_CMP_SEL_CFGA, /*CFGRAM2:  */
    `CS_ALU_OP_PASS, `CS_SRCA_A0, `CS_SRCB_D0,
    `CS_SHFT_OP_PASS, `CS_A0_SRC_NONE, `CS_A1_SRC_NONE,
    `CS_FEEDBACK_DSBL, `CS_CI_SEL_CFGA, `CS_SI_SEL_CFGA,
    `CS_CMP_SEL_CFGA, /*CFGRAM3:  */
    `CS_ALU_OP_PASS, `CS_SRCA_A0, `CS_SRCB_D0,
    `CS_SHFT_OP_PASS, `CS_A0_SRC_NONE, `CS_A1_SRC_NONE,
    `CS_FEEDBACK_DSBL, `CS_CI_SEL_CFGA, `CS_SI_SEL_CFGA,
    `CS_CMP_SEL_CFGA, /*CFGRAM4:  */
    `CS_ALU_OP_PASS, `CS_SRCA_A0, `CS_SRCB_D0,
    `CS_SHFT_OP_PASS, `CS_A0_SRC_NONE, `CS_A1_SRC_NONE,
    `CS_FEEDBACK_DSBL, `CS_CI_SEL_CFGA, `CS_SI_SEL_CFGA,
    `CS_CMP_SEL_CFGA, /*CFGRAM5:  */
    `CS_ALU_OP_PASS, `CS_SRCA_A0, `CS_SRCB_D0,
    `CS_SHFT_OP_PASS, `CS_A0_SRC_NONE, `CS_A1_SRC_NONE,
    `CS_FEEDBACK_DSBL, `CS_CI_SEL_CFGA, `CS_SI_SEL_CFGA,
    `CS_CMP_SEL_CFGA, /*CFGRAM6:  */
    `CS_ALU_OP_PASS, `CS_SRCA_A0, `CS_SRCB_D0,
    `CS_SHFT_OP_PASS, `CS_A0_SRC_NONE, `CS_A1_SRC_NONE,
    `CS_FEEDBACK_DSBL, `CS_CI_SEL_CFGA, `CS_SI_SEL_CFGA,
    `CS_CMP_SEL_CFGA, /*CFGRAM7:  */
    8'hFF, 8'h00,  /*CFG9:  */
    8'hFF, 8'hFF,  /*CFG11-10:  */
    `SC_CMPB_A1_D1, `SC_CMPA_A1_D1, `SC_CI_B_ARITH,
    `SC_CI_A_ARITH, `SC_C1_MASK_DSBL, `SC_C0_MASK_DSBL,
    `SC_A_MASK_DSBL, `SC_DEF_SI_0, `SC_SI_B_DEFSI,
    `SC_SI_A_DEFSI, /*CFG13-12:  */
    `SC_A0_SRC_ACC, `SC_SHIFT_SL, 1'h0,
    1'h0, `SC_FIFO1_BUS, `SC_FIFO0_BUS,
    `SC_MSB_DSBL, `SC_MSB_BIT0, `SC_MSB_NOCHN,
    `SC_FB_NOCHN, `SC_CMP1_NOCHN,
    `SC_CMP0_NOCHN, /*CFG15-14:  */
    10'h00, `SC_FIFO_CLK__DP,`SC_FIFO_CAP_AX,
    `SC_FIFO_LEVEL,`SC_FIFO__SYNC,`SC_EXTCRC_DSBL,
    `SC_WRK16CAT_DSBL /*CFG17-16:  */
}
)) PDM8(
        /*  input                   */  .reset(1'b0),
        /*  input                   */  .clk(clock),
        /*  input   [02:00]         */  .cs_addr(3'b0),
        /*  input                   */  .route_si(1'b0),
        /*  input                   */  .route_ci(1'b0),
        /*  input                   */  .f0_load(1'b0),
        /*  input                   */  .f1_load(1'b0),
        /*  input                   */  .d0_load(1'b0),
        /*  input                   */  .d1_load(1'b0),
        /*  output                  */  .ce0(),
        /*  output                  */  .cl0(),
        /*  output                  */  .z0(),
        /*  output                  */  .ff0(),
        /*  output                  */  .ce1(),
        /*  output                  */  .cl1(),
        /*  output                  */  .z1(),
        /*  output                  */  .ff1(),
        /*  output                  */  .ov_msb(),
        /*  output                  */  .co_msb(co_msb),
        /*  output                  */  .cmsb(),
        /*  output                  */  .so(),
        /*  output                  */  .f0_bus_stat(),
        /*  output                  */  .f0_blk_stat(),
        /*  output                  */  .f1_bus_stat(),
        /*  output                  */  .f1_blk_stat()
);
//`#end` -- edit above this line, do not edit this line
endmodule
//`#start footer` -- edit after this line, do not edit this line

//`#end` -- edit above this line, do not edit this line



  至此,8位PDM部件MyPDM8B已经完成。就如PSoC Creator的其他部件一样,可以在开发环境中使用了。

  例如,我们可以回到TopDesign的线路设计,在Default Component Catalog中找到MyPDM8B部件,把它拖放到设计图中。两个部件自动被命名为MyPDM8B_1、MyPDM8B_2(图8)。

图8

  在程序中,只须按需对Datapath中的D0寄存器赋值就可以了。

  例如

    /* Feed datapath with new value */

    CY_SET_REG8(MyPDM8B_1_PDM8_u0__D0_REG, new_value); // 0~255

  具体可参见文(1)中的实例。


  上面仅介绍8位硬件PDM的做法,而16位硬件PDM的做法可依此类推。

  PSoC4只有4块UDB,只可做4个8位硬件PDM,或2个16位硬件PDM。而PSoC3及PSoC5有有24块UDB,灵活性就大了。


How to Realize the Hardware PDM with PSoC UDB

- A PDM Algorithm Based On Addition (4)


===

FY_ZHU

2013-08-15 BOS-MA


基于累加的PDM算法(1) - 只用一条加法指令实现的PWM算法,软硬都行

基于累加的PDM算法(2) - 基于累加的PDM算法的原理

基于累加的PDM算法(3) - 硬件PWM与基于累加的硬件PDM的比较