使用微码控制器来控制LED闪烁模式

微码控制器可以干什么

在CISC结构下,运行一些复杂的指令时,我们可以利用微码控制器,把复杂的指令分解成一系列简单的指令。通过本次实验,我们将更深刻理解该分解的过程。

任务介绍

我们已经成功地在实验中设计了流水灯外设。现在,你需要一个微码控制器,来轻松更改流水灯的运行模式。Cortex-M0通过总线向微码控制器写一个起始地址,微码控制器便从这个起始地址开始执行微程序。微程序存储在一个存储器中。

01

本次实验的SoC

我们实现了如上图所示的一个SoC。微码流水灯结构可以分成以下三部分,首先为存放微码数据(程序机器码)的双口 RAM,一个读写端口通过 AHB 总线与 M0 处理器连接,一个读端口连接到微码控制器(controller)。其次是微码控制器(controller),负责根据处理器所给的配置信息,读取对应的微码,配置信息为微码的起始地址 s_addr、结束地址 e_addr 和 GPIO 的输入数据 indata,当 GPIO 配置为输入模式时有效。最后一个部分就为实验三所介绍的 GPIO。 我们本次任务的目的是用微码控制器来控制GPIO,以实现流水灯的功能。本次实验的指令类型如下:

普通指令

Bit[31:28] Bit[27:8] Bit[7:0]
普通指令(0x0) 保留字段 控制字段(GPIO输出)

跳转指令

Bit[31:28] Bit[27:16] Bit[15:8] Bit[7:0]
跳转指令(0x1) 保留字段 跳转地址 控制字段(GPIO输出)

两种指令的控制字段均是用于控制当前GPIO的输出状态。对于跳转指令,跳转地址是指执行完当前指令后,下一条需要执行的指令的地址。 控制器工作时的查找表如下所示,具体的实现流程将在下面代码示例中讲到。

01

硬件模块代码

第一步,在 "AHBlite_Decoder.v" 中 GPIO (Port 5和6) 端口参数将其使能:

    /*MicroCode_controller enable parameter*/
    parameter Port5_en = 0,
    /************************/

    /*MicroCode_RAM enable parameter*/
    parameter Port6_en = 0
    /************************/

改为:

    /*MicroCode_controller enable parameter*/
    parameter Port5_en = 1,
    /************************/

    /*MicroCode_RAM enable parameter*/
    parameter Port6_en = 1
    /************************/

第二步,本实验中微码控制器的四个控制字分配地址空间如下:

  • 起始地址s_addr: 0x40000030
  • 终止地址e_addr: 0x40000034
  • 使能信号enable: 0x40000038
  • GPIO模式控制GPIO input: 0x4000003c

与之前实验相同, 在"AHBlite_Decoder.v" 的译码部分插入微码控制器的译码器代码.

//0x40000030 START ADDR
//0X40000034 END ADDR
//0X40000038 ENABLE
//0X4000003c GPIO INPUT (read only)
/*Insert MicroCode_controller decoder code there*/
assign P5_HSEL = 1'b0;
/***********************************/

//0x40001000-0x400013ff
/*Insert MicroCode_controller decoder code there*/
assign P6_HSEL =1'b0;;
/***********************************/

改为

//0x40000030 START ADDR
//0X40000034 END ADDR
//0X40000038 ENABLE
//0X4000003c GPIO INPUT (read only)
/*Insert MicroCode_controller decoder code there*/
assign P5_HSEL = (HADDR[31:4] == 28'h4000003) ? Port5_en : 1'd0;
/***********************************/

//0x40001000-0x400013ff
/*Insert MicroCode_controller decoder code there*/
assign P6_HSEL = (HADDR[31:12] == 20'h40001) ? Port6_en : 1'd0;
/***********************************/

第三步,进行微码控制器的指令译码. 在Microcode_controller中, 将

/*Insert MicroCode decoder code there*/
  assign opc =              ;
  assign branch =           ;
  assign value =             ;
/***********************************/

改为

/*Insert MicroCode decoder code there*/
  assign opc = MicroCode[31:28];
  assign branch = MicroCode[15:8];
  assign value = MicroCode[7:0];
/***********************************/

接下来, 需要在顶层模块中将微码存储器总线接口与微码控制器的总线接口分别与总线扩展模块的 P6、P5 端口连接,微码存储器和微码控制器以及它们的总线接口都已经在顶层模块 "CortexM0_SoC.v" 中例化完成, 只需要将其总线接口的连线部分补充完毕, 实现正确的端口连接.

至此, 我们就完善好了所有 SoC 的硬件代码.

软件模块代码

这是LED闪烁模式的示例代码.

; Finish function code 
BLINK          LDR R6, =0x00           ;s_addr VALUE
                    STR R6,    [R2]
                    LDR R6, =0x01          ;e_addr VALUE
                    STR R6,    [R3]
                    LDR R6,    =0x01
                    STR R6,    [R4]
                    B BLINK

根据上面的代码,补充下面几行,实现

  • LAB3中提到的流水灯(左移模式,右移模式)
  • 学号后2位的LED显示(二进制编码,使用LED1-LED7,其中LED1为最高位)
/*Finish waterlight code*/


/*end*/

调试与运行

Modelsim仿真

照实验二所述, 新建 modelsim 工程, 将之前编写的 verilog 文件添加进工程, 编译并开始仿真, 观察波形, 可以看到流水灯速度正确设置, 流水灯模式在按照控制器中既定模式正确运行.

硬件调试

将修改好的硬件代码综合布线后生成比特流文件,下载到FPGA中. 再按照之前实验讲述的方法连接调试器与PC,打开Keil调试并查看结果。 观察LED灯,能够看到LED按照软件模块中代码所设定的模式运行,Keil调试界面也能够看到寄存器的值正确变化. 可以通过修改MircoCode.txt文件中的内容修改闪烁模式. 比如最后一行中的100012ff,就代表LED全亮模式.

results matching ""

    No results matching ""