可编程逻辑单元PLB的应用

PLB可以通过软件配置实现多种逻辑功能,无需软件参与,大大提高MCU的运行效率。本文旨在全面介绍可编程逻辑单元(PLB)的特性和应用,帮助读者快速理解和掌握PLB的设计和调试方法。文档分为多个章节,涵盖了PLB的基本概念、特性、应用实例、调试技巧以及常见问题解答等内容。

本文对应SDK版本 v1.7.0。

1.1 组合逻辑

物理量抽象

在数字逻辑中,用逻辑运算符来描述物理量之间的逻辑关系。例如:可以使用1和0分别表示一件事情的是和非,真和伪,好和坏,表示电路的通和断,LED灯的亮灭。虽然在这种逻辑中,每个变量的取值只有0和1两种可能,只能表示两种不同的状态,但是通过使用多个变量的不同组合状态组合表示事物的多种逻辑状态,处理任何复杂的逻辑。

这种组合逻辑电路的设计的过程中通常最重要的一步就是进行逻辑抽象,在许多情况下,提出的设计要求是用文字描述的一个具有一定因果关系的事件。这时需要通过逻辑抽象的方法,用一个逻辑抽象的函数来描述这一因果关系。逻辑抽象的方法通常是这样的:

  • 分析事件的因果关系,确定输入变量和输出变量。一般总是把引起事件的原因定义为输入变量,而把事件的结果作为输出变量
  • 定义逻辑状态的含义
    以二值逻辑的0和1分别代表输入变量和输出变量的两种不同状态。这里0和1的具体含义完全由设计者选定。
  • 根据给定的因果关系列出逻辑真值表

至此,便将一个实际的逻辑问题抽象成了一个逻辑函数。而且这个逻辑函数是以真值表的形式给出的。这也和PLB中提供的真值表可以对应起来。

举例

下面是一个经典问题,设计一个监视交通信号灯工作状态的逻辑电路,每一组信号灯均由红、绿、黄三盏灯组成。任何时刻必须有且只有一盏灯点亮。如下表所示,如果是异常的五种状态,则发生故障,这是需要发出故障信号,以提醒相关人员去维护。

状态 绿
正常
正常
正常
异常
异常
异常
异常
异常
  • 首先进行逻辑抽象

取红、绿、黄灯的状态作为输入变量,分别用R, G, Y表示,并规定灯亮时为1,灭时为0。取故障信号为输出变量,以Z表示,并规定正常工作状态Z为0,发生故障时Z为1。根据上文可以列出下表所示的逻辑真值表。

R G Y Z
0 0 0 1
0 0 1 0
0 1 0 0
0 1 1 1
1 0 0 0
1 0 1 1
1 1 0 1
1 1 1 1
  • 选择合适的引脚通过TRGMUX连接到PLB外设,TRGMUX接入的信号电平状态和上一步中真值表的状态需要一致,比如用Y、G、R的状态对应PLB查找表的TRIG_IN0、TRIG_IN1、TRIG_IN2,Z对应PLB查找表的TRIG_OUT0

  • 将真值表的Z值0x00E9写入PLB的TYPE_A[LOOKUP_TABLE]中。

    • 0x00E9 = 0000 0000 1110 1001
    • 使用接口
      plb_type_a_lut.val = 0x00E9;
      plb_type_a_set_lut(BOARD_PLB_COUNTER, BOARD_PLB_CHN, plb_type_a_table0, &plb_type_a_lut);

1.2 时序逻辑

在各种复杂的数字电路中,不但需要对二值信号进行逻辑运算,还经常需要将这些信号和运算结果保存起来,为此需要使用具有记忆功能的基本逻辑单元。能够存储1位二值信号的基本单元电路称为触发器(Flip-Flop)。而PLB的TypeA类型通道具有一个D触发器,所以可以通过这一个D触发器配合前级的组合电路,形成相对复杂的时序功能。

D触发器特性表

CLK D Q(t) Q(t+1)
0 0 保持 保持
0 1 保持 保持
1 0 任意 0
1 1 任意 1

CLK:时钟信号。0表示时钟低电平,1表示时钟高电平。
D:输入信号。0表示低电平,1表示高电平。
Q(t):当前状态下的输出。
Q(t+1):下一个状态下的输出。

当 CLK = 0 时,无论输入 D 的值如何,输出 Q 都会保持不变。
当 CLK = 1 时,输出 Q 在下一个时钟周期会根据输入 D 的值进行更新:

  • 如果 D = 0,则 Q(t+1) = 0
  • 如果 D = 1,则 Q(t+1) = 1

因此,触发器可以被认为是一个时序逻辑单元,它通过时钟信号和输入信号,在时钟周期内实现输出信号的更新和保持。

举例:

对输入信号的上升沿检测,当检测到上升沿时,输出高电平并保持不变。

  • 步骤上和组合逻辑类似,区别是需要充分利用D触发器的特性形成更加复杂的功能,将D触发器的输出接回输入然后可以写出真值表

IN是输入信号,Q是输出信号,t为当前时刻的输出,t+1为下一个时刻的输出

INPUT Q(t) Q(t+1)
0 0 0
0 1 1
1 0 1
1 1 1
  • TRIG_IN0、TRIG_IN1分别对应TRIG_OUT0和输入信号
  • 同样将真值表中的Q(t+1)的值0x000e写入TYPE_A[LOOKUP_TABLE]
    • 0x000e = 0000 0000 0000 1110
    • 使用接口
          plb_type_a_lut.val = 0x000E;
          plb_type_a_set_lut(BOARD_PLB_COUNTER, BOARD_PLB_CHN, plb_type_a_table0, &plb_type_a_lut);

      1.3 复杂逻辑

复杂逻辑主要是计数、移位、运算、比较、赋值功能,PLB实现了这些功能,用户按照如下方法操作即可

  • 分析事件的因果关系,确定输入变量和输出变量。输出变量为操作方法,在“TYPE B功能描述”章节中的typeb数据单元的操作中给出。
  • 定义逻辑状态的含义
    以二值逻辑的0、1两种状态代表输入变量不同状态。这里0和1的具体含义完全由设计者人为选定的。输出的含义就是选定的PLB功能
  • 根据给定的因果关系列出逻辑真值表

    输入信号为IN0-IN2,来自TRGMUX,数据单元的值为x,可以列出真值表如下: IN2 IN1 IN0 Y 含义
    0 0 0 0 x值保持不变
    0 0 1 0 x值保持不变
    0 1 0 0 x值保持不变
    0 1 1 3 x值从cmp[2]获取
    1 0 0 0 x值保持不变
    1 0 1 6 x值=x值减去1,每个时钟周期减一次
    1 1 0 1 x值从cmp[0]获取
    1 1 1 1 x值从cmp[0]获取

    Y的值给到PLB的TYPE_B[LOOKUP_TABLE]中,输入信号0、1、2在不同的状态下对应真值表中不同的Y的功能

    Y的功能如下所示:

    typedef enum plb_type_b_slice_opt {
    plb_slice_opt_keep = 0,                 /**< The data unit keeps the value of the previous cycle */
    plb_slice_opt_get_cmp0_val = 1,         /**< The data unit will take the value of the cmp0 register as the value for the next cycle */
    plb_slice_opt_get_cmp1_val = 2,         /**< The data unit will take the value of the cmp1 register as the value for the next cycle */
    plb_slice_opt_get_cmp2_val = 3,         /**< The data unit will take the value of the cmp2 register as the value for the next cycle */
    plb_slice_opt_add_one = 4,              /**< The next cycle value of the data cell is the current value plus 1 */
    plb_slice_opt_add_two = 5,              /**< The next cycle value of the data cell is the current value plus 2 */
    plb_slice_opt_sub_one = 6,              /**< The next cycle value of the data cell is the current value minus 1 */
    plb_slice_opt_sub_two = 7,              /**< The next cycle value of the data cell is the current value minus 2 */
    plb_slice_opt_shift_left = 4 << 8,      /**< The value of the next cycle of the data cell is shifted one place to the left of the current value */
    plb_slice_opt_shift_left_add_one = 5 << 8,  /**< The next cycle value of the data cell is the current value shifted one place to the left, with the lower bit complemented by one */
    plb_slice_opt_shift_right = 6 << 8,     /**< The value of the next cycle of the data cell is shifted one place to the right of the current value */
    plb_slice_opt_shift_right_add_one = 7 << 8, /**< The next cycle value of the data cell is the current value shifted one place to the right, with the lower bit complemented by one */
    } plb_type_b_slice_opt_t;
    

    TYPE_B[MODE]可配置为

    typedef enum plb_type_b_cmp_mode {
    plb_cmp_mode_out_zero = 0,          /**< output zero */
    plb_cmp_mode_out_one = 1,           /**< output one */
    plb_cmp_mode_gt = 2,                /**< Data unit greater than cmp output one, otherwise output zero */
    plb_cmp_mode_lt = 3,                /**< Data unit less than cmp output one, otherwise output zero */
    plb_cmp_mode_eq = 4,                /**< Data unit equal to cmp output one, otherwise output zero */
    plb_cmp_mode_ne = 5,                /**< Data unit not equal to cmp output one, otherwise output zero */
    plb_cmp_mode_ge = 6,                /**< Data unit greater than or equal to cmp output one, otherwise output zero */
    plb_cmp_mode_le = 7,                /**< Data unit less than or equal to cmp output one, otherwise output zero */
    plb_cmp_mode_and_mask = 10,         /**< The data cell corresponding to the bit set to one by cmp is and */
    plb_cmp_mode_or_mask = 11,          /**< The data cell corresponding to the bit set to one by cmp is or */
    plb_cmp_mode_xor_mask = 12,         /**< The data cell corresponding to the bit set to one by cmp is xor */
    plb_cmp_mode_nand_mask = 13,        /**< The data cell corresponding to the bit set to one by cmp is nand */
    plb_cmp_mode_nor_mask = 14,         /**< The data cell corresponding to the bit set to one by cmp is nor */
    plb_cmp_mode_xnor_mask = 15,        /**< The data cell corresponding to the bit set to one by cmp is xnor */
    } plb_type_b_cmp_mode_t;

    它决定了对于x值进行的操作方法。如选择plb_cmp_mode_eq表示x如果等于当前cmp的值,当前cmp值对应的TRIG_OUT引脚输出1,否则输出0

    举例:

有一个按键,按下时为高电平,松开为低电平,对按下动作进行滤波,滤波时间为500个PLB时钟周期。

  • 抽象,按键IO端的状态为IN0,滤波后的状态为OUT1
  • 定义逻辑状态,按下时为1,松开时为0
  • 定义真值表,并将Y值写入TYPE_B[LOOKUP_TABLE]

    IN0 Y 含义
    0 1 x值从cmp[0]获取,cmp[0]值为0
    1 4 x值加1

使用如下接口设置真值表的功能

    plb_type_b_set_lut(BOARD_PLB_COUNTER, BOARD_PLB_CHN, 0, plb_slice_opt_get_cmp0_val);
    plb_type_b_set_lut(BOARD_PLB_COUNTER, BOARD_PLB_CHN, 1, plb_slice_opt_add_one);
  • 通过TYPE B的结构图可知,一个数据单元有4个比较单元,每个比较单元有一个输出到TRGMUX,所以如果需要OUT1输出给TRGMUX,就需要配置比较单元CMP1,配置CMP1的值为500,且配置TYPE_B[MODE].OUTn_SEL为2。即大于500时OUT1输出1,否则输出0。
    plb_type_b_set_cmp_mode(BOARD_PLB_COUNTER, BOARD_PLB_CHN, plb_type_b_cmp2, plb_cmp_mode_gt);
    plb_type_b_set_cmp_val(BOARD_PLB_COUNTER, BOARD_PLB_CHN, plb_type_b_cmp1, 500);

需要注意,如果长时间按住按键,当PLB的频率为200MHz时,持续按下21秒,当计数值超过32位后,会重新计数,导致输出一段时间的低电平。所以在使用计数和滤波功能时,应当充分考虑计数溢出对功能的影响,可以通过增加上下限检测的功能来确保不会溢出。

  • 通过软件注入TYPE_B[SW_INJECT]更新数据单元的值为0
    plb_type_b_inject_by_sw(BOARD_PLB_COUNTER, BOARD_PLB_CHN, 0);

1.4 调试PLB

在设计和实现基于PLB的数字电路时,调试是一个非常重要的环节。有效的调试方法可以帮助开发者快速定位问题,确保系统正常运行。本章节将介绍一些常用的调试技巧

常见问题及解决方法

  • 配置错误
    问题:PLB寄存器配置错误,导致功能不正常。
    解决方法:仔细检查配置代码,确保所有寄存器的值都正确无误。可以使用调试工具读取寄存器的值,确认寄存器的实际值是否符合预期。
  • 信号时序问题
    问题:信号时序不匹配,导致逻辑功能失效。
    解决方法:使用示波器或逻辑分析仪检查信号时序,确保所有信号的上升沿和下降沿都在预期的时间点。调整时钟信号或延时设置,以优化时序。
  • 逻辑错误
    问题:组合逻辑或时序逻辑设计错误,导致输出不符合预期。
    解决方法:重新检查逻辑真值表和设计思路,确保逻辑关系正确。可以使用仿真工具模拟逻辑电路的行为,找出问题所在。
  • 计数溢出
    问题:计数器溢出,导致输出错误。
    解决方法:设置合理的计数上限,并使用软件检测机制来复位计数器。确保计数器在达到上限时能够正确复位。
  • 外部干扰
    问题:外部干扰导致信号不稳定。
    解决方法:使用示波器观测信号,确认输入输出信号质量。
2
0
发表回复 0

Your email address will not be published. Required fields are marked *