《基于VHDL的乒乓球游戏机的设计与实现(26页).doc》由会员分享,可在线阅读,更多相关《基于VHDL的乒乓球游戏机的设计与实现(26页).doc(26页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、-基于VHDL的乒乓球游戏机的设计与实现-第 23 页乒乓球游戏机的设计与实现摘要:本文介绍了乒乓球游戏机的设计,并进行了程序仿真,实现一个乒乓球游戏机的规定功能。设计的乒乓球游戏机能够正确判断与显示乒乓球的位置,并能自动裁判和记分的装置,可应用于实际的乒乓球游戏比赛中。程序通过调试运行,实现了设计目标。本论文对系统的功能设计、实现流程及正确使用都做了详细的描述。系统开发平台为MAX+PLUSII,程序设计语言为VHDL。关键词:乒乓球游戏机;设计;实现;VHDL;MAX+PLUS; Design and realization of table tennis game playerAbstr
2、act: This article introduces the design of the table tennis game player, and carried out simulation procedures, implementation of the provisions of a table tennis game features. Designed to be able to correctly judge the table tennis game table and display the location, and can automatically appear
3、and scoring devices, can be applied to the actual game of Table Tennis Game. Procedure debugging operations, implementation of the design objectives. This thesis describes in detail the function of the system design, implementation and proper use of flow are described in detail to do. System develop
4、ment platform for the MAX + PLUSII, programming language for VHDL. .Keywords: table tennis game player; design; realization; VHDL; MAX + PLUS 目 录1 引言11.1 课题设计的目的11.2 课题设计的内容22 EDA、VHDA简介32.1 EDA的发展概况32.2 硬件描述语言-VHDL.33 乒乓球游戏机设计过程53.1设计规划53.2乒乓球实体的设计63.3 状态机编程实现73.4 记分译器的设计103.5 构造体的设计124 系统仿真144.1系统
5、编译144.2系统有关波形的仿真14结束语17致谢18参考文献19附录201 引 言08年奥运,在电视机前欢腾了半个晚上。看着白色的乒乓球在屏幕中央跳来跳去,心中的喜悦也在不断积累。又一枚金牌归我中华。课业繁重,但闲暇时,总喜欢在校园中徜徉,每每看到跳动的乒乓,就有种轻衫衬跳脱的轻松感。因此,看到这次的论文选题,不禁哑然失笑,两种风牛马不相及的事物,就这样在这里纠结了。乒乓球作为中国的国球,乒乓人才辈出。本课程设计就是以乒乓球为背景,利用所学的硬件知识完成一个乒乓球游戏机的设计。随着科学技术的发展,人类社会已进入到高度发达的信息化社会, 信息社会的发展离不开电子产品的进步。现代电子产品的发展越
6、来越快, 各种新型电子元器件和智能化的电子产品已经在国民经济的各个领域和人民生活的各个方面得到了日益广泛的应用。实现这种进步的主要原因就是生产制造技术和电子设计技术的发展。其中电子玩具的发展也是在日益成熟。乒乓球游戏机控制电路是有甲、乙双方参赛,有裁判控制发“球”的三人乒乓球游戏机;它能完成自动裁判和自动计分是一个带数字显示的模拟游戏机。其结构简单、成本低、易操作,安全性强、无污染。乒乓球游戏机还能在娱乐的同时提高我们的反应、应变能力。具有良好的市场发展前景1。1.1课题设计的目的本文应用状态机,设计了一个乒乓球游戏机的状态机。状态机的实现是符合人的思维逻辑的,且简单明了2。计算机组成原理课程
7、设计是重要的综合性实践教学环节。 (1)通过该课程设计,结合计算机科学的理论、抽象和设计三种形态,进一步掌握计算机中各功能部件的工作原理和逻辑实现,熟悉乒乓球游戏机的基本工作原理。(2)通过该课程设计的学习,总结计算机组成原理课程的学习内容,运用所学的数字电路以及计算机组成和状态机的基本原理、基本知识和基本技巧,解决某一个具体的实际问题,培养综合分析和解决问题的能力。(3)为今后分析、设计、开发以及使用计算机打下坚实的基础。1.2 课题设计的内容本文设计的是一个乒乓球游戏机的状态机。利用VHDL,不需要按照传统的设计方法进行烦琐的状态分配、绘制状态、化简状态方程等,就可以简单地根据MDS图直接
8、对状态机进行描述。乒乓球游戏机可以实现如下功能。(1)该设计一个由甲、乙双方参赛,有裁判的3人乒乓球游戏机。(2) 用8个(或更多个)LED排成一条直线,以中点为界,两人乒乓游戏机是用8个发光二极管代表乒乓球台,中间两个发光二极管兼做乒乓球网,用点亮的发光二极管按一定方向移动来表示球的运动,在游戏机的两侧个设置发球和击球开关,甲乙双方按乒乓球比赛规则来操作开关。(3)当“球”(点亮的那只LED)运动到某方的最后一位时,参赛者应能果断地按下位于自己一方的按钮开关,即表示启动球拍击球。当甲方按动乒乓球开关时,靠近甲方的第一个发光二极管亮,然后发光二极管由甲方方向依次点亮,代表乒乓球的移动。当球过网
9、后按照设计者规定的球位乙方就可以击球。若乙方提前击球或者未击到球,则甲方得分。然后重新发球进行比赛。(4)设置自动记分电路,甲、乙双方各用7段译码管进行记分显示,每计满21分为1局,然后记分清零,重新开始新一局比赛。2 EDA、VHDL简介2.1 EDA发展概况电子设计技术的核心就是EDA技术,EDA是指以计算机为工作台,融合应用电子技术、计算机技术、智能化技术最新成果而研制成的电子CAD通用软件包,主要能辅助进行三方面的设计工作,即IC设计、电子电路设计和PCB设计。EDA技术已有30年的发展历程,大致可分为三个阶段。70年代为计算机辅助设计(CAD)阶段,人们开始用进行IC版图编辑、PCB
10、布局布线,取代了手工操作。80年代为计算机辅助工程(CAE)阶段。与CAD相比,CAE除了有纯粹的图形绘制功能外,又增加了电路功能设计和结构设计,并且通过电气连接网络表将两者结合在一起,实现了工程设计。CAE的主要功能是:原理图输入,逻辑仿真,电路分析,自动布局布线,PCB后分析。90年代为电子系统设计自动化(EDA)阶段2。硬件描述语言HDL是相对于一般的计算机软件语言,如:C、PASCAL而言的。HDL语言使用与设计硬件电子系统的计算机语言,它能描述电子系统的逻辑功能、电路结构和连接方式。设计者可利用HDL程序来描述所希望的电路系统,规定器件结构特征和电路的行为方式;然后利用综合器和适配器
11、将此程序编程能控制FPGA和CPLD内部结构,并实现相应逻辑功能的的门级或更底层的结构网表文件或下载文件。目前,就FPGA/CPLD开发来说,比较常用和流行的HDL主要有ABEL-HDL、AHDL和VHDL3。2.2 硬件描述语言VHDLVHDL的英文全名是Very-High-Speed Integrated Circuit HardwareDescription Language,诞生于1982年。1987年底,VHDL被IEEE和美国国防部确认为标准硬件描述语言 。自IEEE公布了VHDL的标准版本,IEEE-1076(简称87版)之后,各EDA公司相继推出了自己的VHDL设计环境,或宣布
12、自己的设计工具可以和VHDL接口。此后VHDL在电子设计领域得到了广泛的接受,并逐步取代了原有的非标准的硬件描述语言。1993年,IEEE对VHDL进行了修订,从更高的抽象层次和系统描述能力上扩展VHDL的内容,公布了新版本的VHDL,即IEEE标准的1076-1993版本,(简称93版)。现在,VHDL和Verilog作为IEEE的工业标准硬件描述语言,又得到众多EDA公司的支持,在电子工程领域,已成为事实上的通用硬件描述语言。专家认为,在新的世纪中,VHDL于Verilog语言将承担起大部分的数字系统设计任务。 VHDL主要用于描述数字系统的结构,行为,功能和接口。除了含有许多具有硬件特征
13、的语句外,VHDL的语言形式和描述风格与句法是十分类似于一般的计算机高级语言。VHDL的程序结构特点是将一项工程设计,或称设计实体(可以是一个元件,一个电路模块或一个系统)分成外部(或称可是部分,及端口)和内部(或称不可视部分),既涉及实体的内部功能和算法完成部分4。在对一个设计实体定义了外部界面后,一旦其内部开发完成后,其他的设计就可以直接调用这个实体。这种将设计实体分成内外部分的概念是VHDL系统设计的基本点。应用VHDL进行工程设计的优点是多方面的4。 (1)与其他的硬件描述语言相比,VHDL具有更强的行为描述能力,从而决定了他成为系统设计领域最佳的硬件描述语言。强大的行为描述能力是避开
14、具体的器件结构,从逻辑行为上描述和设计大规模电子系统的重要保证。 (2)VHDL丰富的仿真语句和库函数,使得在任何大系统的设计早期就能查验设计系统的功能可行性,随时可对设计进行仿真模拟。 (3)VHDL语句的行为描述能力和程序结构决定了他具有支持大规模设计的分解和已有设计的再利用功能。符合市场需求的大规模系统高效,高速的完成必须有多人甚至多个代发组共同并行工作才能实现。(4)对于用VHDL完成的一个确定的设计,可以利用EDA工具进行逻辑综合和优化,并自动的把VHDL描述设计转变成门级网表。 (5)VHDL对设计的描述具有相对独立性,设计者可以不懂硬件的结构,也不必管理最终设计实现的目标器件是什
15、么,而进行独立的设计4。3 乒乓球游戏机设计过程3.1设计规划 根据乒乓球比赛的过程和规则,首先游戏开始,如果一方非正确击球则另一方加分,当分数大于21时获胜,游戏结束,我们把设计流程规定如图3.1所示。游戏开始正确接发球?大于21? 甲 乙 否 否大于21?乙方胜利甲方胜利甲方加分乙方加分 N N Y Y游戏结束图3.1设计流程图状态机设置了7个状态,分别是“等待发球状态”,“第一盏灯亮状态”,“第八盏灯亮状态”,“球向乙移动状态”,“ 球向甲移动状态”,“允许甲击球状态”,“允许乙击球状态”。这是该程序中起决定作用的七个状态。开始的时候处于“等待发球状态”,若甲发球则状态转移到“第一盏灯亮
16、状态”,若乙发球则转移到“第八盏灯亮状态”,具体说明以甲球为例。若发球后乙没有提前击球-规定球移动到对方第一个发光二极管时允许击球,那么状态机从“第一盏灯亮状态”转移到“球向乙移动状态”。若在“球向乙移动状态”乙仍然没有提前击球,状态就转移到“允许乙击球状态”,在此状态下,如果乙击球了,那么状态就转移到“ 球向甲移动状态”。在“第一盏灯亮状态”, “球向乙移动状态”中,如果乙击球了 ,就算提前击球,这样甲得分,状态转移到“等待发球状态”等待发球,“ 球向甲移动状态”之后的过程和前面的过程只不过是甲乙角色的调换而已。状态转移规则都是一样的。图3.2给出了乒乓球游戏机的原理图。等待发球 甲得分 乙
17、得分 甲发球 乙发球第一盏灯亮第八盏灯亮允许甲发球球向甲移动 乙击球 甲击球球向乙移动 乙击球 甲击球允许乙发球 乙没击球 甲没击球图3.2 乒乓球游戏机原理图3.2乒乓球游戏机实体的设计该乒乓球游戏机的设计主要包括的模块与内容有:乒乓球游戏机实体的设计,游戏机编程的实现,记分译码器的设计以及构造体的设计。直接对状态机进行描述,所有的状态均可表达为CASE_WHEN结构中的一条CASE语句,而状态的转移则通过IF_THEN_ELSE语句实现。以下我们就详细解析各个板快的设计与实现。设计该乒乓球游戏机的输入与输出端口。首先考虑输入端口,一般应该设置一个异步置位端口reset,用于在系统不正常时回
18、到初始状态:两个发球输入端serve1和serve2,逻辑1分别表示甲方和乙方的发球;两个击球输入端hit1和hit2,逻辑1分别表示甲击球和乙击球;一个开始游戏按钮startbutton,处于逻辑1表示可以游戏;还得有一个时钟输入端口clk。其次考虑输出端口,芯片应该有8个输出端口来控制8个发光二极管,输出逻辑1即输出一个高电平,可以使发光二极管点亮;另外,要直观地表示双方的得分,就得用到4个七段译码器,每方用到2个,可以表示0到21的数字,每个七段译码器需要芯片的7个输出端口来控制,总共28个输出端口。实体的设计如下:library ieee;use ieee.std_logic_1164
19、.all;use ieee.std_logic_arith.all;use ieee.std_logic_unsigned.all; /引用必要的库函数和包集合entity pingponggame is -实体名为pingponggame port(reset:int std_logic;clk:int std_logic;startbutton:int std_logic; -开始游戏输入端口serve:in std_logic_vector(1 to 2); -发球输入端口hit1,hit2:int std_logic; -甲和乙的击球输入端口-控制8个发光二极管的输出端口light:o
20、ut std_logic_vector(1 to 8); score11,score12,score21,score22:out std_logic_vector(1 to 7)); -4个用于控制4个7段译码器的输出端口end pingponggame;3.3状态机编程实现 状态机设置了7个状态,分别是waitserve, light1on, ballmoveto2, Allow2hit,light8on,ballmoveto1,和allow1hit它们代表的具体数值依次是0到6。在波形模拟图中是用数值来表示状态的。 在整个程序中,状态机起的是中央控制器的作用,由它控制的信号来影响整个程序中
21、的其他相关部分,如记分部分,发光二极管部分。乒乓球游戏机中有两个计数器count1和count2,分别记忆甲和乙的得分,用发光二极管的轮流发光表示球的移动轨迹。状态机的进程如下:process(clk) -clk作为敏感信号触发进程begin -进程开始if reset=1 then -异步置位i=0;count100000;count2=00000;elsif clkevent and clk=1 then -当处于时钟inclock上升沿时 if count1=10101or count2=10101theni=0;count100000;count2=00000;elsif startb
22、utton+0 theni=0;count100000;count2 -进程处于等待发球状态case serve iswhen 10= i=1;state i=8;statei i -进程处于第一盏灯亮状态i=2if hit2=1 theni=0;count1=count1+1;state=waitserve; elsestate -进程处于第八盏灯亮状态i=7;if hit=1 theni=0;count2=count2+1;state=waitserve;elsestate -进程处于球向乙移动状态if hit1=1 theni=0;count2=count2+1;state=waitse
23、rve;elsif i=2 then i=1;state=allow1hit;else i -进程处于球向乙移动状态if hit2=1theni=0;ount1=count1+1;state=waitserve;elsif i=7 then i=8;state=allow2hit;else i -进程处于允许甲击球状态if hit1=1 then i=2;state=ballowto2;else count2=count2+1;i=0;state -进程处于允许乙击球状态if hit2=1then i=7;state=ballmoveto1;else count1=count1+1;i=0;s
24、tate=waitserve;end if;end case;end if;end if;end process;3.4记分译码器的设计 七段译码器是在数学电路设计中经常用到的显示电路。所谓七段译码器,其实是由7段发光二极管组成的用于显示数字的器件。记分译码器(mydecoder):由于记分需要显示出来,所以要使用七段译码器。而状态机中的记分是由5位二进制码来表示的,即count1和count2。以下程序就是实现从5位二进制码转换成七段译码显示。library ieee;use ieee.std_logic_1164.all;use ieee.std_logic_arith.all;use i
25、eee.std_logic_unsingned.all; entity mudecoder isport(binaryin:int std_logic_vector(1 to 5); -5位二进制码的输入端口bcdout1:out std_logic_vector(1 to 7); -七段译码器输出端口bcdout2:out std_logic_vector(1 to 7)end mydecoder;architecture m of mydecoder issignal tembinaryin:std_logic_vector(1 to 5);beginprocess(binaryin)be
26、gintembinaryinbcdout1=1111110;bcdout2bcdout1=1111110;bcdout2bcdout1=1111110;bcdout2bcdout1=1111110;bcdout2bcdout1=1111110;bcdout2bcdout1=1111110;bcdout2bcdout1=1111110;bcdout2bcdout1=1111110;bcdout2bcdout1=1111110;bcdout2bcdout1=1111110;bcdout2bcdout1=0110000;bcdout2bcdout1=0110000;bcdout2bcdout1=01
27、10000;bcdout2bcdout1=0110000;bcdout2bcdout1=0110000;bcdout2bcdout1=0110000;bcdout2bcdout1=0110000;bcdout2bcdout1=0110000;bcdout2bcdout1=0110000;bcdout2bcdout1=0110000;bcdout2bcdout1=1101101;bcdout2bcdout1=1101101;bcdout2bcdout1=1101101;bcdout2=1111110;end case;end process;end m; 这个记分译马电路是针对乒乓球游戏机的特点
28、进行的特别设计,采用的是全部列举的方法。3.5 构造体的设计该构造体紧跟在实体设计之后,这样就完成了数字乒乓球游戏机的VHDL源程序编写。rchitecture game of pingponggame istype pingpong is (waitserve,light1on,ballmoveto2,allow2hit,light8on,ballmoveto1,allow1hit);-设置7个状态,为枚举数据类型,记为pingpong signal state:pingpong;signal i:integer range 0 to 8;signal count1,count2:std_l
29、ogic_vector(1 to 5):=00000; -内部计数器,是5位二进制变量component mydecoder isport(binaryin: in std_logic_vector(1 to 5);bcdout1:out std_logic_vector(1 to 7);bcdout2:out std_logic_vector(1 to 7);end component; -调用记分译码器beginprocess(clk) -状态机进程beginend process; -进程处i信号控制发光二极管的亮暗light=10000000when(i=1) else01000000
30、 when(i=2) else00100000 when(i=3) else00010000 when(i=4) else00001000 when(i=5) else00000100 when(i=6) else00000010 when(i=7) else00000001 when(i=8) else00000000; -其他情况所有发光二极管都暗u0:mydecoder port map(count1,score11,score12); -用七段译码器显示甲的分数u1:mydecoder port map(count2,score21,score22); -用七段译码器显示乙的分数end
31、 game;从构造体设计中可以看到,控制整个乒乓球游戏机运转的就是状态机进程,它队各个外围部分起控制作用。它是整个程序的核心,起到一个中心控制器的作用。而外围的部分,比如分数显示,球的轨迹,都是通过它传出的信号来控制。状态机中的i信号和count1,count2信号的变化同时就可以影响到外围的显示部分-发光二极管和七段译码器,从而表示出当时的乒乓球位置和双方分数情况。4 系统仿真4.1系统的编译 编译时选择所要下载的芯片为EPM7128SLC84-15,在编译完成以后,会出现两个警告,信息是这样的:“Primitive score112is stuck at VCC”和“Primitive s
32、core212is stuck at VCC”。这说明score11(2)和score21(2)端口输出一直是1。 score11(2)是用来表示甲得分的十位数字的七段译码器的b段的,由于在记分译码器设计中,十位数字只会显示0,1或者2,无论是这三个数字中的那一个,b段的发光二极管都是亮的,所以就相当于接着高电平VCC。Score21(2)同理。提示信息如图4.1所示。图4.1 编译时警告信息图4.2 系统有关波形的仿真 编译完成后,进行波形仿真,仿真波形图如图4.2所示。图4.2 乒乓球游戏机波形仿真图一 在这个仿真图中,看到serve数组为1,代表乙发球。I从8开始依次递减计数,控制发光管
33、亮暗light信号也随着i的数值变化,见图4.3所示。由light端口输出的高电平驱动芯片以外的发光二极管使之点亮,这样就可以通过发光二极管模拟乒乓球的运动轨迹。可以看到,在甲该击球的时候没有击球,也就是hit1在state状态6的时候没有高电平1输入,则乙得分,count2由0变1,score22的值随之变化。从最后一行state值的变化,可以清楚分析状态转移。图4.3 乒乓球游戏机仿真波形图一中的乒乓球移动状况图4.4是乙发球以后,甲在正确时刻接球的波形仿真图。图4.4 乒乓球游戏机波形仿真图二甲在state为状态6的时候击球了,在图上hit1在此时刻出现高电平,看到state转移到了状态
34、2。当到了状态3乙没有击球,所以甲得分了,count1由0变到1,而七段译码器随之改变。在图4.5中可以清楚地看到球的移动轨迹。图4.5 乒乓球游戏机仿真波形图二中的乒乓球移动状况下面仿真甲提前击球的情况,如图4.6所示。在不允许甲击球的状态下,即state处在状态5时,hit1输入逻辑1,表示甲击球了,所以乙得分。这种情况下球的移动状况如图4.7所示。图4.6 乒乓球游戏机波形仿真图三图4.7 乒乓球游戏机仿真波形图三中的乒乓球移动状况结束语在课题设计中,通过使用MAX+PLUS这个完全集成化、易学易用的可编程逻辑设计环境,利用VHDL语言设计的乒乓球游戏机,较成功的完成了预期的效果,能够正
35、确判断与显示乒乓球的位置,并能自动裁判和记分的装置。在具体设计过程中还需要改进的是控制系统的纠错功能。由于时间关系,系统功能实现不够完善,这些都需要不断的改进和补充。这次课程设计总的说来收获很大。在最初的设计过程中,一共整理出好几个方案。但在实际的过程中发现,设计的情况和实际中还是有些差异的,通过比较得出最优方案。此外,也学会了使用MAX+PLUS软件。这次课程设计虽然短暂。但却是我独立自主的从设计电路到得出结论。书本上的内容第一次完完全全的综合运用。在设计过程中。遇到了书本中不曾学到的知识,经过请教老师和同学,以及查阅相关的资料,最终攻克。致 谢在论文的准备和写作阶段,我遇到了很多难题,也从
36、中认识到了自己专业知识的不足和设计思维上与老师们的差距。本文是在指导老师 XXX老师的悉心指导下完成的,XXX老师在学术上严格要求,老师的教诲和鼓励,及在学术上一丝不苟的精神,本人受益匪浅,在此向XXX老师表示衷心的感谢和敬意!参考文献1 刘艳. EDA 技术在数字系统电路设计实验中的应用J. 实验室研究与探索,2002,21(3): 632642 徐颖.Protel 99 SE EDA技术及应用M.西安:机械工业出版社.20053 杨恒,卢飞成. FPGA/VHDL快速工程实践入门与提高M.北京航空航天大学出版社.20034甘历.VHDL应用与开发实践M.科学出版社.20035卢杰,赖毅.
37、VHDL与数字电路设计M. 北京:科学出版社,20015刘建成,严婕. 电子技术实验与设计教程M. 北京:电子工业出版社,2007附录:主要VHDL源程序/ 程序名称:change.vhd/ 程序作者:陈 梁/ 最后修改日期:2009-3-2 library ieee;use ieee.std_logic_1164.all;use ieee.std_logic_arith.all;use ieee.std_logic_unsigned.all;ENTITY change ISPORT(first:IN STD_LOGIC;- 首发是谁 score1,score2:IN integer rang
38、e 0 to 11;- 当前比分 total1,total2: IN integer range 0 to 4;- 当前总比分 total: OUT integer range 0 to 7; - 总比分和 ends,who:OUT STD_LOGIC); - 比赛是否结束标志,当前发球权END ENTITY;ARCHITECTURE main OF change ISSIGNAL who_temp,first_temp:STD_LOGIC;SIGNAL temp:integer range 0 to 21;BEGINfirst_temp = first;temp = score1 + sco
39、re2; -当前比分和ends = 1 when total1 = 4 OR total2 = 4 - 当一方获胜4局时比赛结束else 0;who_temp = first_temp when (temp=0 OR temp=1 OR temp=4 OR temp=5 OR temp=8 OR temp=9 OR temp=12 OR temp=13 OR temp=16 OR temp=17 OR temp=20) else NOT first_temp when (temp=2 OR temp=3 OR temp=6 OR temp=7 OR temp=10 OR temp=11 OR
40、temp=14 OR temp=15 OR temp=18 OR temp=19) else who_temp; -根据总比分和交换发球权who = who_temp;total = total1 + total2;END ARCHITECTURE;/ 程序名称:tabletennis.vhd/ 程序作者:陈 梁/ 最后修改日期:2009-3-2library ieee;use ieee.std_logic_1164.all;use ieee.std_logic_unsigned.all;ENTITY tabletennis ISPORT(clk,p1,p2,reset,speed_sel,first_sel,judge:IN STD_LOGIC; led:OUT STD_LOGIC_VECTOR(7 downto 0); cat:OUT STD_LOGIC_VECTOR(5 downto 0); digit:OUT STD_LOGIC_VECTOR(6 downto 0);END ENTITY;ARCHITECTURE ma