libraryIEEE;useIEEE.std_logic_1164.all;useIEEE.numeric_std.all;entitymux_Aisport(sel:instd_logic;e_0,e_1:instd_logic_vector(11downto0);s:outstd_logic_vector(11downto0));endmux_A;architecturearch_mux_Aofmux_Aisbegin--***************************************-- A COMPLETER ----***************************************endarch_mux_A;
libraryIEEE;useIEEE.std_logic_1164.all;useIEEE.numeric_std.all;entitymux_Bisport(sel:instd_logic;e_0,e_1:instd_logic_vector(15downto0);s:outstd_logic_vector(15downto0));endmux_B;architecturearch_mux_Bofmux_Bisbegin--***************************************-- A COMPLETER ----***************************************endarch_mux_B;
Un multiplexeur est un composant combinatoire permettant d’aiguiller une information.
On utilisera pour la description VHDL soit :
l’affectation conditionnelle ( s <= a when choix=’0’ else b),
un process combinatoire, à condition de mettre dans la liste de sensibilité du process toutes les entrées du composant.
muxA et muxB répondent à la même description, seuls les tailles des vecteurs d’entrée et de sortie diffèrent (12 pour muxA, 16 pour muxB)
La notion de généricité peut être utilisée dans ce cas.
libraryIEEE;useIEEE.std_logic_1164.all;useIEEE.numeric_std.all;entitytristateisport(oe:instd_logic;data_in:instd_logic_vector(15downto0);data_out:inoutstd_logic_vector(15downto0));endtristate;architecturearch_tristateoftristateisbegin--***************************************-- A COMPLETER ----***************************************endarch_tristate;
Une porte 3 états est un composant combinatoire permettant de contrôler le forçage des niveaux logiques d’un bus.
Dans notre cas, si l’entrée oe est à ‘1’, alors l’entrée data_in sera vue sur la sortie data_out ; sinon la sortie sera à l’état haute impédance (‘Z’).
libraryIEEE;useIEEE.std_logic_1164.all;useIEEE.numeric_std.all;usework.up_pack.all;entityaluisport(A,B:instd_logic_vector(15downto0);alufs:inALU_FCTS;S:outstd_logic_vector(15downto0));endalu;architecturearch_aluofaluisbegin--***************************************-- A COMPLETER ----***************************************endarch_alu;
L’UAL est un composant combinatoire effectuant des opérations arithmétiques et logiques entre les opérandes d’entrée A et B.
L’entrée alufs permet de sélectionner le type d’opération.
Alufs appartient au type ALU_FCTS défini dans le paquetage up_pack.
libraryIEEE;useIEEE.std_logic_1164.all;useIEEE.numeric_std.all;entityaccumulatorisport(clk,raz,load:instd_logic;data_in:instd_logic_vector(15downto0);data_out:outstd_logic_vector(15downto0);acc15,accz:outstd_logic);endaccumulator;architecturearch_accofaccumulatorissignalq_reg:std_logic_vector(15downto0);begin--***************************************-- A COMPLETER ----*************************************** endarch_acc;
Le registre accumulateur a pour rôle de mémoriser le résultat de l’UAL présent sur data_in lorsque load=’1’.
Ce résultat est alors visible sur data_out.
accz vaut ‘1’ quand data_out est nulle.
acc15 correspond au bit de poids fort de la donnée mémorisée.
libraryIEEE;useIEEE.std_logic_1164.all;useIEEE.numeric_std.all;usework.up_pack.all;entityir_regisport(clk,raz,load:instd_logic;data_in:instd_logic_vector(15downto0);data_out:outstd_logic_vector(11downto0);opcode:outOPCODE);endir_reg;architecturearch_ir_regofir_regissignalinterne:std_logic_vector(3downto0);begin--***************************************-- A COMPLETER ----***************************************opcode<=OP_LDAwheninterne="0000"elseOP_STOwheninterne="0001"elseOP_ADDwheninterne="0010"elseOP_SUBwheninterne="0011"elseOP_JMPwheninterne="0100"elseOP_JGEwheninterne="0101"elseOP_JNEwheninterne="0110"elseOP_STPwheninterne="0111"elseOP_ANDwheninterne="1000"elseOP_ORwheninterne="1001"elseOP_XORwheninterne="1010"elseOP_LDRwheninterne="1011"elseOP_LDIwheninterne="1100"elseOP_STIwheninterne="1101"elseOP_JSRwheninterne="1110"elseOP_RETwheninterne="1111"elseOP_UNKNOWN;endarch_ir_reg;
Le registre IR a pour rôle de mémoriser le code de l’instruction présent sur le bus de données (entrée data_in) , lorsque ir_ld=’1’.
On tachera d’utiliser un signal interne std_logic_vector de taille 4 dans lequel seront copiés les 4 bits de poids fort du signal d’entrée,
tandis que data_out sera affectés avec les 12 bits de poids faibles du signal d’entrée.
opcode (appartenant au type OPCODE défini dans le paquetage up_pack) répondra alors à l’affectation suivante (en parallèle du process synchrone) :
libraryIEEE;useIEEE.std_logic_1164.all;useIEEE.numeric_std.all;entitypc_regisport(clk,raz,load:instd_logic;data_in:instd_logic_vector(11downto0);data_out:outstd_logic_vector(11downto0));endpc_reg;architecturearch_pc_regofpc_regisbegin--***************************************-- A COMPLETER ----***************************************endarch_pc_reg;
libraryIEEE;useIEEE.std_logic_1164.all;useIEEE.numeric_std.all;usework.up_pack.all;entitysequenceurisport(clk,reset:instd_logic;accz,acc15:instd_logic;opcode:inOPCODE;raz:outstd_logic;selA:outstd_logic;selB:outstd_logic;acc_ld,pc_ld,ir_ld,acc_oe:outstd_logic;alufs:outALU_FCTS;memrq,rnw:outstd_logic);endsequenceur;architecturearch_seqofsequenceuristypeme_statesis(INIT,FETCH,EXECUTE,STOP);signaletat_cr,etat_sv:me_states;beginprocess(clk,reset)beginifreset='1'thenetat_cr<=INIT;elsifrising_edge(clk)thenetat_cr<=etat_sv;endif;endprocess;process(etat_cr,opcode,accz,acc15)beginetat_sv<=etat_cr;raz<='0';selA<='0';selB<='0';acc_ld<='0';acc_oe<='0';pc_ld<='0';ir_ld<='0';alufs<=ALU_B_INC;memrq<='1';rnw<='1';caseetat_criswhenINIT=>etat_sv<=FETCH;raz<='1';whenFETCH=>etat_sv<=EXECUTE;ir_ld<='1';-- load IR with data on the data busalufs<=ALU_B_INC;-- op = B+1pc_ld<='1';-- load PC with PC+1whenEXECUTE=>caseopcodeiswhenOP_LDA=>selA<='1';-- IR[mem] on addr busselB<='1';alufs<=ALU_B;-- op = Bacc_ld<='1';-- load data in accumulatoretat_sv<=FETCH;whenOP_STO=>selA<='1';-- IR[mem] on addr busacc_oe<='1';-- output accumulator on data busrnw<='0';-- select write to memoryetat_sv<=FETCH;whenOP_ADD=>selA<='1';-- IR[mem] on addr busselB<='1';-- data to B alu entryalufs<=ALU_ADD;-- op = A+Bacc_ld<='1';-- load result in accumulatoretat_sv<=FETCH;whenOP_SUB=>selA<='1';-- IR[mem] on addr busselB<='1';-- data to B alu entryalufs<=ALU_SUB;-- op = A-Bacc_ld<='1';-- load result in accumulatoretat_sv<=FETCH;whenOP_JMP=>selA<='1';-- IR[mem] on addr busalufs<=ALU_B;-- op = Bpc_ld<='1';-- load PC with IR[mem]etat_sv<=FETCH;whenOP_JGE=>ifacc15='0'then-- jump, else nothingselA<='1';-- IR[mem] on addr busalufs<=ALU_B;-- op = Bpc_ld<='1';-- load PC with IR[mem]endif;etat_sv<=FETCH;whenOP_JNE=>ifaccz='0'then-- jump, else nothingselA<='1';-- IR[mem] on addr busalufs<=ALU_B;-- op = Bpc_ld<='1';-- load PC with IR[mem]endif;etat_sv<=FETCH;whenOP_STP=>etat_sv<=STOP;whenOP_AND=>selA<='1';-- IR[mem] on addr busselB<='1';-- data to B alu entryalufs<=ALU_AND;-- op = A and Bacc_ld<='1';-- load result in accumulatoretat_sv<=FETCH;whenOP_OR=>selA<='1';-- IR[mem] on addr busselB<='1';-- data to B alu entryalufs<=ALU_OR;-- op = A or Bacc_ld<='1';-- load result in accumulatoretat_sv<=FETCH;whenOP_XOR=>selA<='1';-- IR[mem] on addr busselB<='1';-- data to B alu entryalufs<=ALU_XOR;-- op = A xor Bacc_ld<='1';-- load result in accumulatoretat_sv<=FETCH;whenothers=>etat_sv<=STOP;endcase;whenSTOP=>etat_sv<=STOP;endcase;endprocess;endarch_seq;
3 - Instanciation de mu0
Relier les composants décrits précédemment afin de constituer le système Processeur mu0
libraryIEEE;useIEEE.std_logic_1164.all;useIEEE.numeric_std.all;usework.up_pack.all;usework.all;entitymu0isport(reset,clk:instd_logic;data_bus:inoutstd_logic_vector(15downto0);addr_bus:inoutstd_logic_vector(11downto0);mem_rq:outstd_logic;rnw:outstd_logic);endmu0;architecturearch_mu0ofmu0issignalopcode:OPCODE;-- opcode operationsignalraz:std_logic;-- raz for registerssignalir_out:std_logic_vector(11downto0);-- output of IRsignalpc_out:std_logic_vector(11downto0);-- output of PCsignalalu_out:std_logic_vector(15downto0);-- output of ALUsignalacc_out:std_logic_vector(15downto0);-- output of ACC signalmuxb_out:std_logic_vector(15downto0);-- output of MUXbsignalconcat:std_logic_vector(15downto0);signalalufs:ALU_FCTS;-- function code for alusignalir_ld:std_logic;-- load IRsignalpc_ld:std_logic;-- load PCsignalacc_ld:std_logic;-- load ACCsignalacc_oe:std_logic;-- enable out buffersignalselA:std_logic;-- multiplexer A selectsignalselB:std_logic;-- multiplexer B selectsignalaccZ:std_logic;-- accumulator all zero'ssignalacc15:std_logic;-- accumualtor sign bitbegin--***************************************-- A COMPLETER ----***************************************endarch_mu0;
REMARQUE : Le test de mu0 seul est inutile, il est nécessaire d’associer la mémoire à mu0.
libraryieee;useieee.std_logic_1164.all;useieee.numeric_std.all;usework.all;entitymu0_memisport(clk:instd_logic;reset:instd_logic;data_bus:inoutstd_logic_vector(15downto0);addr_bus:inoutstd_logic_vector(11downto0));endmu0_mem;architecturearch_mu0_memofmu0_memissignalMEMRQ:std_logic;-- memory requestsignalRNW:std_logic;-- read/write opbegin--***************************************-- A COMPLETER ----***************************************endarch_mu0_mem;
Instancier le processeur mu0 avec la mémoire RAM (dans laquelle est écrit le programme à exécuter)
dans un composant nommé mu0_mem puis tester le fonctionnement de l’ensemble.
5 - Modification du programme en Mémoire
Modifier le programme de la RAM pour tester l’opération de soustraction ainsi que JMP et JGE