Tutoriais e Programação

AoA - Laboratório Cap.2 II

Dom

25

Fev

2007


16:48

  • Imprimir
(4 votos, média 5.00 de 5) 


Houve uma época em que os engenheiros raciocinavam em termos de portas e circuitos. Nos projetos digitais atuais, eles fornecem uma série de equações lógicas para um programa que transforma estas equações numa série de bits que podem ser programados em PLA, PAL ou FPGA. Linguagens lógicas e compiladores de silício transformaram muitos dos projetos de circuitos digitais em exercícios de programação. Apesar disto, os engenheiros ainda usam pequenos circuitos integrados, como AND, OR ou inversores. Mesmo que você se considere um programador "puro" e pretende evitar projetos de hardware a qualquer custo, ainda assim precisa estar preparado para ler esquemas de circuitos digitais simples porque, provavelmente, vai ter que escrever um programa que, em algum ponto, tenha que interfacear com o hardware. Esta é uma das razões pela qual um curso de lógica digital precisa fazer parte da Ciência da Computação.


{faqslider} :::: Circuitos eletrônicos e expressões booleanas ::::

Mesmo que, durante toda a sua vida, você nunca tenha colocado a mão num circuito integrado AND, OR ou inversor, ainda assim é interessante aprender a ler e desenhar diagramas de circuitos simples. Um esquema eletrônico fornece uma representação visual de uma função lógica. Na maior parte das vezes, é mais fácil ler e entender um esquema do que ler e entender um tabela verdade ou uma expressão booleana.

Apesar de existirem milhares de símbolos eletrônicos, vamos precisar apenas de três, porque podemos projetar qualquer circuito lógico usando apenas os AND, OR e NOT lógicos. Os símbolos esquemáticos correspondentes são:

Portas AND, OR e NOT
Fig.1 - Portas AND, OR e inversora (NOT)
X = AB + A'B'
Fig.2a - X = AB + A'B'
X = AB + A'B' simplificado
Fig.2b - X = AB + A'B' simplificado

As linhas do lado esquerdo de cada símbolo representam as entradas da função. O símbolo especifica a função e a linha à direita de cada símbolo é a saída da função. Geralmente, símbolos como A, B, C, D e outras letras maiúsculas representam entradas ou saídas de circuitos. Saídas intermediárias que alimentam outras entradas em algum ponto do circuito geralmente não recebem nomes simbólicos. Por exemplo, a função X = AB + A'B' teria o aspecto mostrado na Fig.2a. Como os inversores aparecem com frequência numa expressão booleana, adotaremos a convenção de usar um pequeno círculo na linha de entrada ou de saída para indicar a negação lógica. O circuito acima pode ser redesenhado como mostrado na Fig.2b.

A = 0 e B = 1
Fig.3a - A = 0 e B = 1
Calculando as saídas
Fig.3b - Calculando as saídas

Esta função lógica, por sinal, é a exclusive-NOR ou função de igualdade.

Para rastrear um circuito lógico e determinar suas saídas, atribui-se inicialmente valores para as variáveis das linhas de entrada. Por exemplo, se A = 0 e B = 1, começamos colocando um zero em cada linha identificada por A e um 1 em cada linha identificada por B. Confira o exemplo na Fig.3a.

O valor da saída final
Fig.3c - O valor da saída final

O próximo passo é calcular as saídas para cada porta (função) que estas linhas de entrada estejam alimentando.

O processo deve ser repetido até que se encontre a saída final da função, como mostrado na Fig.3c.






question Q02.51 - Dadas as entradas A = 1 e B = 1, indique todos os resultados para o esquema da função X = AB + A'B'

Fechar

question Q02.52 - Dadas as entradas A = 0 e B = 0, indique todos os resultados para o esquema da função X = AB + A'B'

Fechar

question Q02.53 - Faça um esquema para a função exclusive-OR (XOR ou não igual)

Fechar


:::: :::: Circuitos combinatórios ::::
Circuito sequencial
Fig.4 - Circuito sequencial (não combinatório)

Circuitos combinatórios, que usam a lógica combinatória, possuem saídas que dependem apenas das suas entradas atuais. As saídas refletem imediatamente as alterações nas entradas. Na verdade, circuitos eletrônicos reais precisam de um pequeno período de tempo até que os sinais das entradas cheguem nas saídas. Neste texto, os retardos de propagação serão ignorados.

As portas AND, OR e inversoras são exemplos de circuitos combinatórios simples. Uma restrição importante destes é que não precisam de nenhum retorno (feedback), isto é, uma entrada para uma porta não pode ser um resultado de uma função que dependa da saída desta mesma porta. Isto significa que não é possível obter loops em circuitos combinatórios. Por exemplo, o circuito da Fig.4 não é um circuito combinatório porque as entradas para as portas NAND dependem das próprias saídas.

Decodificador para a entrada 1010
Fig.5 - Decodificador para a entrada 1010

Um decodificador é um bom exemplo de um circuito combinatório. Este é um circuito que produz um valor específico (geralmente zero) quando um valor específico ou um conjunto de valores específicos aparece nas suas entradas. Por exemplo, veja na Fig.5 um circuito decodificador simples que produz uma saída zero quando suas quatro linhas de entrada receberem 1010.

Função AND de três entradas
Fig.6 - Função AND de três entradas

Outro conjunto importante de circuitos combinatórios são as portas de n-entradas AND e as portas de n-entradas OR. Por exemplo, se quisermos calcular o AND lógico de três entradas, podemos colocar duas portas AND em cascata como mostrado na Fig.6.

De forma semelhante, podemos construir uma porta AND de quatro entradas ou combinar três portas AND de duas entradas. Veja abaixo:

Variação de porta AND de quatro entradas
Fig.7a - Variação de porta AND de quatro entradas
Variação de porta AND de quatro entradas
Fig.7b - Variação de porta AND de quatro entradas
Porta AND de n-entradas
Fig.8a - Porta AND de n-entradas
Porta OR de n-entradas
Fig.8b - Porta OR de n-entradas

As portas OR de n-entradas podem ser construídas usando o mesmo princípio descrito acima. Como portas AND e OR com mais de duas entradas são muito comuns, usaremos um único símbolo para representar portas de n-entradas.



Esquema para D'CB'A
Fig.9 - Esquema para D'CB'A

Para transformar uma equação lógica num esquema eletrônico começamos construindo uma porta AND de n-entradas para cada termo da expressão. Se aparecer uma literal não plicada no termo, então fornecemos esta entrada diretamente à porta AND; se aparecer uma variável plicada, invertemos esta variável antes de de fornece-la à porta AND (isto é, colocamos um círculo nesta linha de entrada). Por exemplo, o mintermo D'CB'A tem o símbolo esquemático mostrado na Fig.9.


question Q02.54 - Faça os diagramas esquemáticos para CBA' (use uma porta AND de três entradas) e para DCB'A' (use uma porta AND de quatro entradas)

Fechar

Depois de projetar os circuitos para cada um dos termos de uma expressão booleana podemos completar o circuito desta expressão fazendo um OR das saídas das portas AND de cada um dos termos. A função F = CBA + DB' + D'C'BA fica assim representada:

Função F = CBA + DB' + D'C'BA
Fig.10 - Esquema da função F = CBA + DB' + D'C'BA

question Q02.55 - Faça o diagrama esquemático para a função F = DCB'A' + CBA'

Fechar

Termo de porta AND
Fig.11a - Termo de porta AND
Soma de termos de porta OR
Fig.11b - Soma de termos de porta OR

Fazer o caminho inverso para converter um diagrama esquemático numa equação lógica é tão fácil quanto. Todas as entradas de uma porta lógica AND são transformadas em termos (veja a Fig.11a). Todas as entradas de uma porta OR são transformadas em termos da expressão de soma (veja a Fig.11b). Se houver um círculo na entrada, negamos (invertemos) a entrada adicionando uma plica à variável.

Saída alimentando entrada
Fig.12 - Saída alimentando entrada

Se a saída de uma determinada porta alimentar a entrada de outra porta, simplesmente ponha a expressão entre parênteses e a use como a "variável" de entrada da segunda porta. Observe a Fig.12. A saída da porta OR está alimentando uma das entradas da porta AND, então a "variável" que a porta OR envia para a porta AND é (C + B + A). A porta AND recebe (C + B + A), além de D', C e B. A função resultante será D' x C x B x (C + B + A). Não custa relembrar que AND multiplica e que OR soma.



question Q02.56 - Qual é a expressão booleana do circuito mostrado na figura?

Fechar
D'CBA' + A'

question Q02.57 - Qual é a expressão booleana do circuito mostrado na figura?

Fechar
(CBA)' + (D'CBA') + A


:::: :::: Circuitos sequenciais ::::
Flip-Flop com duas NAND
Flip-Flop com duas NAND

Um circuito sequencial é um circuito combinatório com a adição de retornos (feedbacks), isto é, uma ou mais saídas alimentam entradas do circuito. Isto faz com que o circuito guarde operações realizadas anteriormente na memória, ou seja, que faça um histórico. Considere o flip-flop liga/desliga dado como exemplo de um circuito não combinatório na seção anterior (veja ao lado).

Uma das saídas da porta NAND superior é uma entrada da porta NAND inferior e uma das saídas da porta NAND inferior é uma entrada da porta NAND superior. Alguns circuitos sequenciais são instáveis, isto é, a realimentação das entradas pode alterar a saída, a nova saída realimenta a entrada alterando novamente a saída, e assim indefinidamente.

Circuito instável
Fig.13 - Circuito instável

Um exemplo banal de um circuito sequencial instável é um inversor simples com a saída realimentando sua entrada (Fig.13). Neste circuito, uma entrada inicial de 1 produz uma saída 0. O circuito realimenta a entrada com 0, o que produz uma saída 1. A entrada é realimentada com 1 que produz 0 e assim por diante...

Matematicamente, um circuito instável como este é inconsistente. Isto pode ser comparado com uma divisão por zero ou com o logaritmo de um número negativo - não tem como resolver. No mundo da eletrônica, um circuito instável produz oscilação, isto é, a saída salta constantemente entre 0 e 1 numa frequência diretamente relacionada ao retardo de propagação do circuito.

Um circuito estável, por outro lado, fixa-se numa determinada saída e permanece neste estado até que as entradas sejam modificadas. O flip-flop liga/desliga (set/reset) deste exemplo é um circuito estável. Enquanto as entradas não mudarem, as saídas permanecem constantes.

Normalmente as entradas S e R são lógicas. Além disso, Q' deve sempre ser o inverso de Q. Observe a tabela abaixo onde estão os valores iniciais possíveis para estas entradas e saídas (as colunas identificadas com S, R, q' e q). Constatamos que existem oito combinações possíveis.

SRq'q S AND q'Q=NOTR AND q Q'=NOTObservação
1001 010Impossível
2001 001Impossível
3101 010Impossível
41010 1001OK
50101 0110OK
6011 001Impossível
71101 0110OK
81110 1010OK

A seguir analisamos a consistência dos dados. Sabemos que a saída Q corresponde à entrada q e que a saída Q' corresponde à entrada q'. Como o flip-flop é constituído por duas portas NAND, sabemos que Q = NOT(S AND q') e que Q' = NOT(R AND q). As colunas restantes mostram estes cálculos e indicam os resultados conflitantes. Estes aparecem nas configurações 1, 2, 3 e 6. As restantes são estados possíveis neste flip-flop S/R, também chamado de biestável ou circuito oscilante.

Imagine que o flip-flop esteja no estado de repouso indicado na linha 8, ou seja, S = 1, R = 1, q' = 1 e q = 0. Acompanhe na tabela abaixo o que acontece quando modificamos S para 0.

Inicial0 em SS AND q' InverteR AND qInverteS AND q' Final
S1 0S = 0 0S0
q'1q'= 1 Q'0
q0 1Q1
R1R = 1 R1

No instante em que aplicamos 0 na entrada S, acontece S AND q' = 0x1 = 0. Este valor invertido passa a ser Q = 1. O novo valor de Q é enviado para a porta inferior, forçando um NOT(R AND q) = NOT(1x1) = NOT(1) = 0. Este é o novo valor de Q'. Este valor é enviado para a porta superior forçando um novo NOT(S AND q') = NOT(0x0) = NOT(0) = 1. Como este já era o valor anterior de Q (e da entrada q), nada mais se modifica. O novo estado do flip-flop é S = 0, Q' = 0, Q = 1 e R = 1. Observe que as saídas Q e Q' foram alternadas (daí o nome de flip-flop ou oscilatório).

As saídas permanecem neste estado mesmo quando a entrada S voltar para 1. É só seguir o mesmo raciocínio: Q = NOT(S AND q') = NOT(1x0) = NOT(0), ou seja, Q = 1. Como Q continua no mesmo estado anterior, não há mudança na entrada q da porta NAND inferior e o circuito entra em descanso. Neste caso, não ocorreu uma inversão das saídas Q e Q', apenas o valor de S foi mudado.

No primeiro caso, o circuito estava "armado": a aplicação de 0 em S provocou a inversão das saídas Q e Q' e "desarmou" o circuito. No segundo caso, o circuito estava "desarmado" e a aplicação de 1 em S apenas trocou o valor de S. Este flip-flop S/R é um bom exemplo de circuito de memória. Ele guarda (ou lembra) a última entrada que foi alimentada com zero.

question Q02.58 - Quais serão as saídas Q e Q' se você alimentar as duas entradas S e R com zero?

Fechar
Dá caca, porque Q = 1 e Q' = 1 deixam de ser complementares. O circuito fica instável. Como a entrada que fica mais tempo em zero assume o valor zero, Q'= 0 e Q = 1.

question Q02.59 - Como estarão as saídas Q e Q' se você aplicar zero à duas entradas e depois aplicar 1 à entrada R?

Fechar
Q = 0 e Q' = 0

question Q02.60 - Como estarão as saídas Q e Q' se você aplicar zero à duas entradas e depois aplicar 1 à entrada S?

Fechar
Q = 0 e Q' = 1

Latch Transparente (Flip-Flop D)
Fig.14 - Um Latch Transparente (Flip-Flop D)

Tecnicamente falando, o circuito mostrado na Fig.14 é um latch transparente de um bit e não um flip-flop D. Um flip-flop D captura os dados nas entradas quando o clock muda do nível 0 para nível 1 (a borda ascendente do clock). As saídas não se alteram enquanto o clock estiver no estado baixo (0) ou alto (1), apenas quando ocorrer uma transição do nível 0 para o nível 1. O circuito ao lado não funciona desta forma. Enquanto a linha do clock estiver alta, qualquer valor aplicado na entrada de Dados é enviado para a saída Q (e o valor inverso para a saída Q'). É por isto que se trata de um latch transparente: enquanto a linha do clock estiver alta, o circuito é transparente e os dados fluem imediatamente para as saídas. Quando a linha do clock estiver baixa, o último valor da entrada de dados é trancada nas saídas (a tradução de latch é trancar).

Flip-Flop D
Fig.15 - Flip-Flop D

Um flip-flop D verdadeiro apenas captura os valores de entrada de Dados quando a linha do clock passa de baixa para alta. A linha de dados precisa ser estável (manter o mesmo valor) durante esta transição, mas pode conter qualquer outro valor a qualquer tempo, que as saídas não serão afetadas. O circuito de um flip-flop D é mostrado na Fig.15.

Flip-Flop S/R
Fig.15a - Flip-Flop S/R

Assim como para os circuitos combinatórios, também podemos construir expressões booleanas para os circuitos sequenciais. Usaremos o símbolo "#" para indicar a entrada do clock. Para os valores que realimentam o circuito, atribuiremos um nome de variável intermediário (ou o nome da saída da função) e usaremos o nome como se fosse o de uma variável de entrada. Para calcular as saídas de um circuito sequencial usamos os valores de saída anteriores como valores de realimentação do circuito. Por exemplo, considere o estado de um flip-flop set/reset como o da Fig.15a.

Se aplicarmos zero na entrada R, isto força a saída Q' para 1 porque (RQ)' = (0x1)' = 1. A saída Q' realimenta a porta NAND superior de modo que as entradas (Q') = 1 e (S) = 1. Isto força a saída Q para zero.

Para gerar uma expressão booleana para um circuito sequencial, começamos pelas saídas e avançamos na direção das entradas. Atribuiremos os nomes P e Q para as saídas da porta. Apesar das saídas serem identificadas normalmente com Q e Q', neste caso a saída Q' tem uma função diferente - ela não é o complemento da saída Q. As equações resultantes serão Q = (SP)' e P = (RQ)'.

Flip-Flop S/R
Fig.15b - Flip-Flop S/R
Flip-Flop D
Fig.15c - Flip-Flop D

Para um circuito mais complexo, que possua diversas saídas intermediárias que usem outras entradas, precisamos inverter alguns nomes de variáveis para poder representar estas saídas. Considere o flip-flop D da Fig.15c e suas saídas nominadas. Suas funções lógicas serão: F = (GN)', G = (F#)', M = (GN#)', N = (DM)', Q = (GP)' e P = (MQ)'.

question Q02.61 - Quais são as equações lógicas para o circuito latch transparente de 1 bit?

Fechar
Q = (FP)'
P = (GQ)'
F = (D#)'
G = (D'#)'


:::: :::: Simulando lógica com software ::::

Como existe uma relação direta (um para um) entre expressões booleanas e circuitos eletrônicos e uma relação direta (um para um) entre expressões booleanas e programas de computador, então também existe uma relação direta (um para um) entre circuitos eletrônicos e programas de computador. Num curso de projetos digitais você poderá aprender a projetar circuitos que implementem alguns algoritmos. Este tutorial se refere à programação e aqui nos preocuparemos em transformar circuitos eletrônicos em software.

Circuitos combinatórios são muito fáceis de serem implementados em software: basta transformar o circuito numa expressão booleana. Transformar uma expressão booleana numa função numa linguagem de alto nível como C++ ou Pascal é uma tarefa trivial. Considere a expressão booleana para o segmento quatro de um display de sete segmentos:

S4 = D'C'B'A' + D'C'BA' + D'CBA' + DC'B'A'

A função Pascal que implementa esta função é:

function S4(D, C, B, A:boolean):boolean; begin S4 := ((not D) and (not C) and (not B) and (not A)) or ((not D) and (not C) and B and (not (A)) or ((not D) and C and B and (not A)) or (D and (not C) and (not B) and (not A)); end;

O código C++ correspondente é:

int S4(int D, int C, int B, int a) { return (!D && !C && !B && !A) || (!D && !C && B && !A)|| (!D && C && B || !A) || (D && !C && !B && !A); }

Códigos como os mostrados acima demonstram a necessidade de se otimizar uma expressão booleana antes de transformá-la numa função de alto nível. Como você ainda deve se lembrar (pelo menos espero que se lembre smile ), a versão simplificada desta expressão booleana é:

S4 = C'B'A' + D'B(C'A + CA')

Então, o código em C++ passa a ser:

int S4(int D, int C, int B, int A) { return (!C && !B && !A) || (!D && !B && (!C && A || C && !A)); }

A última versão é nitidamente mais curta e rápida, a não ser que você possua um compilador muito bom que seja capaz de otimizar o código anterior. Ainda assim, mesmo dispondo de um excelente compilador, a última versão é melhor porque é mais fácil de ler e de entender.

question Q02.62 - Crie uma função em C++ ou Pascal que implemente a expressão booleana F = A + BC'

Fechar
Pascal:
function F(C, B, A:boolean):boolean;
begin
F := A or (B and not C);
end;

C++:
int F(int C, int B, int A)
{
return A || B && !C;
}

Transformar circuitos sequenciais num programa é um pouco mais complicado porque as saídas dependem de saídas anteriores. Outra complicação é a propagação. Para avaliar a dificuldade com a propagação de sinais, considere as equações lógicas do flip-flop set/reset:

Q = (SP)' e P = (RQ)'

As funções C++ correspondentes podem ser:

int Q(int S, int P) { return !(S && P); } int P(int R, int Q) { return !(R && Q); }

Dados quatro valores, S, R, Qval e Pval, pode-se pensar que é possível calcular os valores de saída (Qval e Pval) usando duas chamadas como:

Qval = Q(S, Pval); Pval = (R, Qval);

O problema desta avaliação simplista é que o cálculo de Qval usa a versão antiga de Pval enquanto que o cálculo de Pval usa o novo valor de Qval. Como as duas saídas dependem uma da outra, teríamos que recalcular o valor de Qval porque este depende do novo valor de Pval.

Qval = Q(S, Pval); Pval = (R, Qval); Qval = Q(S, Pval);

Acontece que este novo cálculo altera o valor de Qval o que, por sua vez, afeta Pval. Neste caso, temos que repetir o cálculo de Pval... e assim indefinidamente. A questão é "quando devemos parar?" Sabemos que, se um circuito for estável, então as saídas também ficarão estáveis depois de uma sequência de n operações, onde n corresponde ao número de funções (portas AND e OR) do circuito (na pior das hipóteses). Como o flip-flop set/reset possui apenas duas portas NAND, precisamos executar as funções de saída apenas duas vezes para obter o resultado correto, ou seja:

Qval = Q(S, Pval); Pval = (R, Qval); Qval = Q(S, Pval); Pval = (R, Qval);

question Q02.63 - Na pior das hipóteses, quantas iterações são exigidas pelo latch transparente de um bit?

Fechar
Na pior das hipóteses, 4 iterações.


:::: :::: Software de apoio ::::
Display
Fig.16 - Display
Números e Segmentos
Fig.16a - Números e Segmentos

Agora que você já trabalhou bastante fazendo uma porção de cálculos e anotações à mão, está na hora de apresentar o software que facilita a vida neste segundo capítulo. Todos os programas oferecidos para download são da autoria de Randall Hyde e foram traduzidos e recompilados pela vovó Vicki vovo

Faremos um giro aproveitando um decodificador de sete segmentos, os quais são identificados de acordo com a Fig.16. Como um display de sete segmentos contém sete valores de saída (um para cada segmento), existirão sete funções lógicas associadas ao display (do segmento zero até o segmento seis).

As quatro entradas para cada uma das sete funções booleanas são os quatro bits de um número binário no intervalo de 0 a 9. Considere a variável D como o bit mais significativo deste número e a variável A como o bit menos significativo deste número. Por exemplo, ao quarto segmento (I), que deve ficar aceso com os números 0, 2, 6 e 8, corresponde a seguinte função:

decimal =    0          2          6          8
binário = 0 0 0 0    0 0 1 0    0 1 1 0    1 0 0 0
      I = D'C'B'A' + D'C'B A' + D'C B A' + D C'B'A'

Faça o download do programa Otimizador de Expressões Booleanas (está na seção de downloads em Tutoriais/Arte do Assembly) e digite a função acima no campo "Equação Lógica". A seguir, clique no botão "Otimizar". O resultado é a função otimizada I = D'C'A' + B'C'A' + BA'D'. Você também pode acompanhar o mapeamento utilizado para a simplificação clicando seguidas vezes no botão "Passo". Crie as funções para os sete segmentos e as otimize.

Agora é a vez do Analisador de Funções (também está na seção de downloads em Tutoriais/Arte do Assembly). Faça o download, instale e rode o programa. Depois proceda da seguinte forma:

  1. na aba "Criar" clique no botão "Adiciona".
  2. Transfira a função otimizada (ou a canônica), I = D'C'A' + B'C'A' + BA'D' para o campo de edição. Certifique-se de que a função está identificada com I. Clique no botão OK.
  3. Clique na aba "Executar". Note que o segmento I está ligado.
  4. Através dos interruptores é possível "ligar" ou "deligar" as variáveis A, B, C e D. Com isto é possível testar a expressão.

Os interruptores permitem indicar o número desejado. O primeiro interruptor liga/desliga A, o segundo B, o terceiro C e o quarto D. Agora ligue o 7, cujo binário é 0111. A sequência dos bits é DCBA, ou seja, A=1 (ligado), B=1 (ligado), C=1 (ligado) e D=0 (desligado). Observe que o segmento se apaga, porque, para obter 7, o segmento I precisa estar desativado. Teste com outros números.

Crie as seis funções restantes. O jogo completo vai de E até K. Transfira estas funções para o programa. Agora é só brincar de acender o display ligando e desligando os bits com os interruptores.

Existem mais dois programas interessantes para download, o Equações Canônicas e o Tabelas Verdade (também estão na seção de downloads em Tutoriais/Arte do Assembly). O primeiro transforma qualquer equação booleana na sua forma canônica e o segundo permite criar expressões canônicas a partir de tabelas verdade de 2, 3 ou 4 variáveis.

Sei que você deve estar pensando "porque a vó não falou do software logo no início do laboratório?" - bem... foi proposital. É que é bom fazer os exercícios propostos na unha para fixar os conceitos - só depois disto o software pode quebrar um galho, porque já sabemos o que estamos fazendo smile


{/faqslider}


игровой автомат columbus колумб онлайн бесплатнобиоклон официальный сайт россиясайт отзывовсамые лучшиелобановский александр биографиякак сделатьbroker mfx