Está en la página 1de 78

Suscríbete a DeepL Pro para poder traducir archivos de mayor tamaño.

Interrupciones Más información disponible en www.DeepL.com/pro.

¿Cuándo NO son adecuadas las interrupciones?

Para responder a esta pregunta hay dos observaciones importantes. La primera es que mientras KCPSM6 está atendiendo una interrupción, no está
haciendo ningún progreso en la ejecución del programa principal (es decir, ¡el programa principal ha sido interrumpido!). En segundo lugar, KCPSM6 sólo
puede dar servicio a una interrupción a la vez, lo que significa que si se produce otra interrupción mientras KCPSM6 está ocupado ejecutando el ISR, la
nueva interrupción se perderá o tendrá que esperar, ninguna de las dos cosas es ideal. En términos generales, un esquema de interrupción no es adecuado
si el ritmo al que se producen las interrupciones es demasiado rápido para que puedan ser atendidas y para que el programa principal progrese
adecuadamente.
Está claro que la definición de "demasiado rápido" depende de lo exigentes que sean tanto el programa principal como el ISR, pero la única constante
absoluta es que cada instrucción KCPSM6 siempre tarda 2 ciclos de reloj en ejecutarse. Así que al menos puedes determinar fácilmente la tasa de
ejecución del código para una frecuencia de reloj dada y compararla con las demandas de tu programa y tu tasa de interrupción esperada.

Por ejemplo, considere el uso de interrupciones generadas a intervalos de 1ms para su uso como referencia de tiempo para un reloj de tiempo real. Con un
KCPSM6 funcionando a una frecuencia de reloj de 66MHz ejecutará 33.000.000 de instrucciones por segundo y por lo tanto podrá ejecutar 33.000
instrucciones entre cada interrupción. Se trata claramente de un gran número y es muy poco probable que impida la capacidad de progresar
adecuadamente a través de cualquier programa estando siempre listo para atender la siguiente interrupción. Pero supongamos que las interrupciones se
generan a intervalos de 1µs con el objetivo de lograr una resolución de tiempo más fina. Ahora el KCPSM6 sólo podría ejecutar 33 instrucciones entre cada
interrupción (es decir, ¡menos instrucciones de las que se pueden imprimir en una cara de un papel!). A menos que la ISR sea muy breve no se completará
a tiempo. Incluso si la ISR fuera sólo de 12 instrucciones, significaría que más de un tercio de la potencia de cálculo se consumiría en el servicio de la
simple ISR y eso significa que el programa principal se ejecutaría proporcionalmente más lento con una "vacilación" asociada causada por las continuas
interrupciones. Esto puede seguir siendo aceptable para la aplicación, pero sin duda está al borde de ser inadecuado y hará muy difícil ampliar las
características implementadas por el código del programa.

¿Cuáles son las alternativas?

Cuando las interrupciones tienen sentido entonces es una característica muy útil de KCPSM6 para explotar. Sin embargo, cuando no son adecuadas, la
ventaja de utilizar una FPGA Xilinx es que existen muy buenas alternativas. El mayor error que la gente comete a menudo es luchar con soluciones

Página Copyright 2010-2014 Xilinx


basadas en interrupciones cuando no son adecuadas. Es mucho mejor explotar soluciones alternativas para hacer el diseño general mucho más fácil de
implementar.

Mayor uso del hardware - Simplemente se implementan circuitos que realizan lo que se hubiera conseguido con el ISR basado en software, de forma que
se evitan las interrupciones o se reduce enormemente su frecuencia. Por ejemplo, un bloque contador/temporizador basado en hardware puede ser muy
sencillo de implementar en hardware y luego KCPSM6 puede leer valores de tiempo de él cuando lo necesite. La complejidad de un reloj en tiempo real
podría seguir implementándose en software, pero la resolución de la temporización la gestionaría mejor el hardware, que es rápido por naturaleza. Las
interrupciones podrían utilizarse ocasionalmente cuando un comparador de hardware coincide con un valor de tiempo establecido por KCPSM6.

¡Divide y vencerás! - Si un procesador KCPSM6 está dedicado al 100% a una tarea, en realidad siempre está ejecutando una ISR. Esto tiene sentido si el
ISR es relativamente complejo como para plantearse implementarlo en hardware. Dado que KCPSM6 es tan pequeño (26 Slices), dedicar un procesador
diferente a cada tarea exigente puede ser a menudo la solución más fácil y mejor. De hecho, PicoBlaze se utiliza a menudo para dar servicio a las
interrupciones de un procesador más grande como MicroBlaze.

Página Copyright 2010-2014 Xilinx


'interrupt_vector ' y 'ADDRESS' Directiva
Consulte las páginas 83-85 para obtener instrucciones relacionadas con las interrupciones.

Cuando el KCPSM6 responde a una interrupción ejecuta el equivalente a una instrucción CALL así como las tareas específicas de la interrupción tales
como preservar los estados de las banderas. El vector de interrupción es la dirección a la que efectivamente llama el KCPSM6 y tiene el valor por defecto
de 3FF hex. Sin embargo, esto se puede ajustar a cualquier valor dentro del rango de la memoria de programa disponible en su diseño utilizando el
genérico 'interrupt_vector' en la descripción de su diseño HDL.
procesador: mapa
genérico kcpsm6 hwbuild => X "00",
interrupt_vector => X Declaración del componente (parte de) mostrando
(
"3FF",
scratch_pad_memory_size => 64) los valores por defecto de los tres genéricos.

port map( dirección => dirección,


instrucción=> instrucción,
Instanciación del componente (parte de) que muestra
Etc... que el vector de interrupción se ha establecido en 'F80'
hex.
procesador: kcpsm6
mapa genérico ( hwbuild => X
"41", Archivo PSM...
interrupt_vector => X DIRECCIÓN F80
DIRECCIÓN Directiva ;
"F80", scratch_pad_memory_size =>
256) ISR : ADD sF, 1'd
Utiliza la directiva ADDRESS en tu código
RETURNI HABILITAR
port map( dirección => dirección, PSM para forzar que el ISR sea ensamblado
comenzando en la misma dirección que el
instrucción => instrucción, vector de interrupción.
Etc...

¿Cuál es una buena dirección para 'interrupt_vector'?

3FF es la última ubicación en una memoria de programa de 1K y es coherente con KCPSM, KCPSM-II y KCPSM3. Así que para la compatibilidad
directa con los programas de legado PicoBlaze esta es la mejor dirección para empezar y por lo tanto la razón por la que es el valor predeterminado.
Por supuesto, puedes modificar el programa y el vector.

Generalmente la dirección más conveniente es alguna cercana al final de la memoria de programa disponible pero dejando suficiente espacio para el ISR.
Esto significa que el ISR puede empezar a dar servicio a la interrupción inmediatamente. También es conveniente desde una perspectiva de
programación porque la directiva ADDRESS debe ser usada para alinear el inicio del código ISR con el vector de interrupción y tener esto como la última

Página Copyright 2010-2014 Xilinx


sección de tu programa PSM permite a tu programa principal la flexibilidad de expandirse hasta él. A medida que tu código se estabiliza, siempre puedes
afinar la coincidencia entre 'interrupt_vector' y la directiva ADDRESS para un mejor ajuste a la memoria.

¿Qué son valores erróneos? Si tratas de poner tu ISR en algún lugar en el medio de tu programa, entonces probablemente encontrarás que siempre estás
teniendo que ajustar la directiva ADDRESS y 'interrupt_vector', lo cual es una pérdida de tiempo inconveniente, así como propenso a errores. ¡La peor
dirección sería cero! Bajo ninguna circunstancia querrás que tu ISR se ejecute al encenderse o después de un reset (RETURNI sólo debería usarse
después de una interrupción).

Página Copyright 2010-2014 Xilinx


El procesador KCPSM6 tiene dos pines dedicados a las interrupciones: una entrada "interrupt" y una salida "interrupt_ack". Para iniciar una interrupción, la
entrada "interrupt" debe ponerse a nivel alto y el tiempo de respuesta fundamental de la interrupción es de sólo 3 ó 4 ciclos de reloj. Como se muestra en la
página siguiente (Formas de onda de interrupción), la entrada de interrupción se muestrea una vez cada dos ciclos de reloj, en consonancia con la
velocidad de ejecución de la instrucción. Por esta razón es vital que la entrada de interrupción esté alta en el momento adecuado para ser observada por el
KCPSM6 y la forma más fácil de conseguirlo es mantener la entrada de interrupción alta durante más de un ciclo de reloj. Hay dos esquemas
fundamentales que se pueden utilizar y que se pueden describir como "bucle abierto" y "bucle cerrado".

Impulso de interrupción de bucle abierto


kcpsm6
La forma más simple de iniciar una interrupción es generar un pulso activo Alto que tenga una duración
de 2 ciclos de reloj. El pulso puede ser más largo, pero debe volver a nivel Bajo antes de que se complete interrumpir
la ISR, de lo contrario KCPSM6 pensará inmediatamente que hay otra interrupción que atender (recuerde
clk
que cada instrucción se ejecuta en 2 ciclos de reloj, por lo que algunas ISR pueden no tardar muchos
ciclos de reloj). Una vez que KCPSM6 observa el nivel Alto en su entrada de interrupción, abandonará la
siguiente instrucción e inmediatamente pasará al ISR.

La simplicidad del método de "bucle abierto" es obvia, pero también hay que reconocer que cualquier sistema de bucle abierto tiene sus limitaciones. En
este caso existe la posibilidad de que el KCPSM6 pase por alto una petición de interrupción y por lo tanto no la atienda. Esto puede ocurrir si el programa
KCPSM6 ha deshabilitado deliberadamente las interrupciones o si ya está atendiendo una ISR previa. El KCPSM6 también ignorará la entrada de
interrupción mientras se encuentre en modo reposo. Por lo tanto, esta técnica sólo se debe utilizar si se puede predecir que KCPSM6 siempre estará listo
para responder a una solicitud de interrupción o si es aceptable que se pierdan interrupciones.

Interrupción en bucle cerrado (recomendada)

En este esquema tu diseño conduce la señal de interrupción a Alto kcpsm6


para solicitar una interrupción y luego sigue conduciéndola a Alto
D Q
hasta que KCPSM6 genera un pulso 'interrupt_ack' confirmando que interrupción
la ha visto. Esto asegura que la interrupción siempre será observada interrupt_ack
por KCPSM6 cuando pueda hacerlo. Si las interrupciones se han R
desactivado temporalmente de forma deliberada, o mientras se daba clk
servicio a una interrupción anterior, entonces la respuesta se
retrasará pero el evento no puede perderse. Del mismo modo, si el
KCPSM6 se mantiene en modo de reposo cuando se solicita la
interrupción, ésta permanecerá activa hasta que el KCPSM6 pueda
despertarse y observarla.
Página Copyright 2010-2014 Xilinx
Sugerencia - Algunos sistemas pueden requerir una disposición de bucle cerrado más completa en la que se esperaría que KCPSM6 indicara cuándo se ha
completado el ISR en lugar de cuando acaba de empezar (que es lo que significa 'interrupt_ack'). Esto se puede conseguir utilizando un puerto de salida
con instrucciones 'OUTPUT' o 'OUTPUTK' asociadas al final de tu ISR. Alternativamente, podrías detectar cuando la instrucción[17:12] = "101001"

Disposiciones de hardware para la interrupción KCPSM6


correspondiente con la instrucción 'RETURNI' que se obtiene de la memoria del programa.

Consulte las páginas 83-85 para obtener instrucciones relacionadas con las interrupciones.

Página Copyright 2010-2014 Xilinx


Formas de onda de
interrupción Consulte las páginas 83-85 para obtener
instrucciones relacionadas con las
interrupciones.
Se produce una interrupción cuando la entrada "interrupt" se pone a nivel alto, el programa ha habilitado las interrupt_control: process(clk)
comience
interrupciones y el KCPSM6 no está en modo de reposo ni ocupado atendiendo una interrupción anterior. if clk'event and clk = '1' then
Cuando el KCPSM6 detecta una interrupción fuerza el abandono de la siguiente instrucción, preserva los if interrupt_ack = '1' then
estados actuales de las banderas 'Z' y 'C', anota la selección de banco actual ('A' o 'B') y entonces fuerza el interrupción <= '0';
contador de programa al vector de interrupción (el valor por defecto es 3FF hex que es la última posición de else
una memoria de programa de 1K pero puede fijarse a cualquier valor usando el genérico 'interrupt_vector'). if kcpsm6_interrupt = '1' then
interrupt <= '1';
si no
Las formas de onda mostradas abajo ilustran una respuesta normal a una interrupción cuando las interrupt <= interrupt;
interrupciones han sido habilitadas dentro del programa y el KCPSM6 está listo para responder. En el end if;
terminar si;
diseño del hardware, el vector de interrupción se estableció en FF0 hex y se utilizó un esquema de terminar si;
interrupción de "bucle cerrado" (implementado por el VHDL que se muestra a la derecha) para garantizar fin proceso interrupt_control;
que el pulso de interrupción no pueda perderse.

La entrada 'interrupt' se muestrea en los flancos de reloj ascendentes que la dirección interrupt_vector => X "FF0",

clk

interrumpir

interrupt_ack

bram_enable

direcci 5A0 5A1 5A2 5A3 FF0 FF1 FF2


ón

inst_5A0 inst_05A1 inst_5A2 inst_5A3 inst_FF0 inst_FF1


instrucción

Se conservan las banderas Z y C. Se conserva la selección de banco. Todo se restablecerá con la instrucción RETURNI.

Página Copyright 2010-2014 Xilinx


Se abandona la última instrucción leída de la memoria de
programa antes de que se produzca la interrupción. Esta
será la primera instrucción ejecutada tras una
RETURNI después de que la interrupción haya sido
atendida.

Página Copyright 2010-2014 Xilinx


Sugerencia - En la mayoría de los casos en los que un usuario informa
de que KCPSM6 no simula en absoluto (por ejemplo, la 'dirección' no
avanza como se esperaba), la causa ha sido el fallo por parte del

Funciones de simulación HDL usuario a la hora de definir niveles lógicos válidos para los controles
'interrupt', 'sleep' y 'reset'. Así que por favor, asegúrate de que todas
las señales están definidas al inicio de tu simulación, ya sea en tu
diseño o en tu banco de pruebas de simulación.

Dado que KCPSM6 es una parte totalmente integrada de su diseño de hardware, se simulará junto con el resto de su diseño en un simulador HDL como
iSim o XSim. Esto significa que puedes ver cómo KCPSM6 interactúa con tu diseño de la misma manera fundamental en la que podrías comprobar el
funcionamiento de una máquina de estados dedicada.
Además de poder observar cualquiera de las señales de
entrada y salida que conectan el KCPSM6 al resto de tu
diseño, el KCPSM6 contiene algunas señales adicionales
específicamente para fines de simulación.

Dentro del simulador localice la instancia de KCPSM6 a


observar. En este caso el nombre de la instancia es
'procesador' y el simulador es iSIM (parte de ISE).

A continuación, todas las señales internas del KCPSM6 se


pueden ver y seleccionar para la visualización de la forma de
onda como se desee. Mira hacia abajo en la lista y las
señales específicas de simulación se pueden encontrar.

kcpsm6_opcode - Se trata de una cadena de texto que muestra el


que se está ejecutando. Además de ser
más fáciles de entender que los códigos
en bruto que se leen de la memoria del
programa, también se pueden comparar
con el archivo LOG del ensamblador para
rastrear directamente la ejecución del
código.

kcpsm6_status - Es una cadena de texto que muestra el


por ejemplo, A, Z, NC, IE, Sleep
estado...
Banco A, Z=1, C=0, interrupciones activadas, en modo reposo
Banco de registro activo 'A' o 'B'
Indicador de cero Z o NZ
Indicador de acarreo C o NC
Interrupciones activadas (IE) o
desactivadas (ID) Modos Reset o Sleep.

Página Copyright 2010-2014 Xilinx


'sim_s0' a 'sim_sf' - El contenido de cada uno de los 16
registros del banco de registros activo
(es decir, el contenido reflejará la
selección del banco).

'sim_spm00' a 'sim_spmff' - El contenido de cada uno de los 256


blocs de notas
posiciones de memoria.
Recuerde que el tamaño de
memoria por defecto es de 64
bytes (sólo hasta sim_spm3f).
Sugerencia - Ajuste el radix de los valores mostrados.

Página Copyright 2010-2014 Xilinx


Funciones de simulación HDL
En esta vista de forma de onda de iSim o Xsim se puede ver lo siguiente...

Cada instrucción tarda 2 ciclos de reloj en ejecutarseCódigos de operación de instrucción descodificados y mostrados como cadenas de
texto.

El contenido de los registros. En este ejemplo podemos ver que 's3' se carga con el contenido Banco de registros 'A', Estados de banderas e
de 's1' seguido de la suma del contenido de 's2'.
interrupción.

Sugerencia - Los programas KCPMS6 a menudo contienen código que se utiliza para ralentizar deliberadamente el progreso a través del programa para dar
servicio a la aplicación correctamente, ya sea utilizando bucles de retardo de software o sondeo de señales de estado. Por ejemplo, cuando se comunica
con una UART que tiene una velocidad BAUD de 115200, cada carácter tardará 86,8µms en recibirse, lo que equivaldría a 8.680 ciclos de reloj de un reloj
de sistema de 100MHz. Debido a esto, no es raro que los usuarios se confundan por lo que perciben como una "falta de actividad" en su diseño simulado
simplemente porque KCPSM6 está tomando tantos ciclos de reloj. Así que si esta es la situación, puede ser necesario alterar el código PSM para que la
simulación HDL sea práctica, pero obviamente tendrás que recordar restaurar el código correcto para la aplicación real. En la práctica, la mayoría del código

Página Copyright 2010-2014 Xilinx


PSM se desarrolla interactivamente en tiempo real en el hardware de destino utilizando JTAG_Loader para facilitar iteraciones rápidas. Como tal, la
simulación HDL se utiliza mejor para confirmar su lógica de interconexión de puertos y la generación de estroboscópicos y formas de onda particulares, etc.

Página Copyright 2010-2014 Xilinx


Durante la fase de diseño y desarrollo del código se utiliza la plantilla por defecto 'ROM_form' con el ensamblador. Esto genera la definición de hardware de
la memoria de programa y los tres genéricos facilitan la especificación de la familia de destino (Spartan-6, Virtex-6 o Serie 7), el ajuste del tamaño de la
memoria y la inclusión del cargador JTAG, que casi con toda seguridad te ha parecido una herramienta inestimable. Aunque esta flexibilidad y el cargador
JTAG son herramientas extremadamente útiles durante el desarrollo, significan que el archivo de definición de memoria de programa generado por el
ensamblador es algo grande y demasiado complicado para una versión de producción. El cargador JTAG puede haber sido una herramienta inestimable
durante el desarrollo, pero dejar el programa KCPSM6 abierto a ajustes en un producto de producción podría suponer una amenaza para la seguridad del
diseño. Por supuesto, usted puede decidir explotar la utilidad JTAG Loader como parte de su producto de producción también, en cuyo caso ¡deje todo
como está!

Para que pueda entrar en producción con la definición de hardware más simplificada de su memoria de programa y asegurarse de que JTAG Loader no
se activa accidentalmente, se proporciona un conjunto de plantillas de "producción". El nombre de cada plantilla de producción describe la familia de
destino ('S6' para Spartan-6, 'V6' para Virtex-6 y '7S' para la serie 7) y el tamaño de la memoria de programa implementada (1K, 2K o 4K instrucciones).
También hay un caso especial que sustituye completamente la BRAM por 18 rebanadas de ROM distribuida y proporciona una implementación muy
eficiente para programas de hasta 256 instrucciones. Haga una copia del archivo apropiado y renómbrelo 'ROM_form.vhd'. A continuación, utilice este
archivo con el ensamblador y su archivo PSM para generar la definición de memoria simplificada.

kcpsm6 tu_programa
[17:0]
instrucción bram_enable active instrucción
[11:0]
direcci Sugerencia - No se
dirección
necesitan genéricos
ón para la memoria fija.
clk

reinic ROM_form_S6_1K_date .vhd


Sug
iar ROM_form_S6_2K_date. vhd
eren ROM_form_S6_4K_date. vhd
cia
Conecta tu señal 'rdl' a clk tu_programa.psm ROM_form.vhd ROM_form_V6_1K_date .vhd
'0'. Esto retiene la señal ROM_form_V6_2K_date. vhd
en su definición de hwbuild => X "00" ROM_form_V6_4K_date. vhd
diseño en caso de que interrupt_vector => X "3FF" ROM_form_7S_1K_date. vhd
necesite volver a la scratch_pad_memory_size => 64 ROM_form_7S_2K_date .vhd
memoria de desarrollo ROM_form_7S_4K_date .vhd
ROM_form_128_date .vhd
de nuevo más tarde.
ROM_form_256_date .vhd
Página Copyright 2010-2014 Xilinx
Sugerencia - Una plantilla 'ROM_form' es un archivo HDL estándar excepto que contiene
Sugerencia - El archivo por defecto 'ROM_form.vhd' es
{tags} especiales que el ensamblador intercepta. Usted puede modificar cualquiera de
una copia renombrada del archivo llamado
las plantillas proporcionadas para definir su propio formato especial de memoria de
'ROM_form_JTAGLoader_14March13.vhd' que también
programa (por ejemplo, una memoria de doble puerto en la que el puerto
Memoria del programa de producción ( ROM_form )
se proporciona en el paquete KCPSM6.
programa puede ser cambiado por un mecanismo diferente a JTAG Loader).

Tenga en cuenta que también se proporciona el equivalente Verilog de


cada archivo.

Página Copyright 2010-2014 Xilinx


Ensamblador y software PSM

Referencia del software PSM


La siguiente información proporciona descripciones más detalladas del ensamblador KCPSM6 y de la sintaxis PSM. En caso necesario, se incluirán
descripciones adicionales
para indicar el contexto en el que se utilizan los grupos de instrucciones.

Sugerencia - Las descripciones de cada una de las instrucciones contienen ejemplos de código PSM. Así que, por favor, no se detenga demasiado
en las descripciones formales pero breves de la sintaxis del ensamblador, porque la mayor parte de esto debería quedar claro a través de los
ejemplos y se convertirá en algo natural para usted una vez que empiece a escribir su propio código. El ensamblador KCPSM6 te proporcionará
rápidamente información cuando proceses tu código, así que sólo tienes que probarlo y dejar que te ayude a aprender la sintaxis precisa de forma
interactiva; ¡pronto serás un experto!

Para complementar esta documentación, se proporciona el siguiente material de referencia adicional en el paquete
KCPSM6 (archivo ZIP)...

all_kcpsm6_syntax.psm - Proporciona un archivo PSM (aunque no es un programa real) en el que hay ejemplos de toda la sintaxis PSM
soportada.
por el ensamblador KCPSM6 incluyendo todas las formas válidas de instrucciones, operandos y directivas.

Sugerencia - 'all_kcpsm6_syntax.psm' contiene las descripciones más completas de la sintaxis PSM y las directivas del
ensamblador. En cambio, este documento centra sus descripciones en el conjunto de instrucciones KCPSM6.

kcpsm6_assembler_readme.txt - Este documento será más atractivo para el usuario avanzado, en particular aquellos que prefieren invocar el
ensamblador como parte de un flujo por lotes. Como tal, este documento es más bien clínico y objetivo.

Sugerencia - Este archivo documenta los problemas y limitaciones conocidos, pero esperamos que no te los encuentres.

Directorios
UART_and_PicoTermEstos directorios incluyen diseños sencillos pero totalmente documentados en los que

Página Copyright 2010-2014 Xilinx


KCPSM6 se presenta en varias placas de diseños de referencia de evaluación . En todos los diseños hay un tema común en el que
las macros UART (proporcionadas en el paquete KCPSM6) son
utilizados para implementar una comunicación sencilla con el usuario . Los diseños incluyen ejemplos de manipulación
de datos (por ejemplo, rutinas de conversión de ASCII hexadecimal a decimal) y la interacción con una variedad de
componentes periféricos incluyendo XADC y la implementación de señalización SPI e I2C y transacciones para leer y
escribir memoria flash externa.

Página Copyright 2010-2014 Xilinx


El ensamblador KCPSM6
El ensamblador KCPSM6 se suministra como un único archivo ejecutable 'kcpsm6.exe'. Puede colocarse en cualquier lugar del sistema, pero en la
mayoría de los casos es más fácil y cómodo colocar una copia en el directorio de trabajo del proyecto ISE (sólo ocupa 109 kbytes).

En la mayoría de los casos, o al menos para empezar, el método interactivo


es adecuado. Basta con hacer doble clic en el ejecutable y se abrirá una
ventana como ésta.

Escriba el nombre de su archivo PSM de nivel superior (no es necesario


que ponga '.psm' al final del nombre, pero el archivo debe tener la
extensión '.psm').

Sugerencia - Un archivo de texto llamado 'kcpsm6_assembler_readme.txt '


contiene información adicional para aquellos interesados en invocar el
ensamblador desde archivos por lotes o usando un método de 'arrastrar
y soltar'.
Sugerencia - Si encuentra algún problema inesperado al utilizar el
ensamblador, consulte la sección "Problemas conocidos y soluciones" del
archivo 'kcpsm6_assembler_readme.txt'.

El ensamblador leerá su archivo PSM de nivel superior e incluirá cualquier


PSM definido por las directivas INCLUDE. A continuación, comprobará la
sintaxis correcta de todas las definiciones y el código.

Si el ensamblador detecta un error en el código PSM,


identificará el archivo PSM y la línea de ese archivo que no
puede resolver y le hará sugerencias para que pueda
rectificar el problema.

A continuación se le presentan 3 sencillas opciones. La opción "R"


significa que puede volver a ejecutar rápidamente el ensamblador tan

Página Copyright 2010-2014 Xilinx


pronto como haya utilizado el editor de texto de su elección para
realizar las modificaciones apropiadas en su archivo PSM (y lo haya
guardado). Esto facilita mucho las iteraciones rápidas.

Página Copyright 2010-2014 Xilinx


El ensamblador KCPSM6

Siempre que tu archivo PSM contenga sintaxis válida entonces el


ensamblador generará una versión perfectamente formateada de tu
programa original que puedes adoptar para que parezca que has estado
trabajando duro todo el día haciendo que algo se vea así de bonito ☺.
Véase el ejemplo de la página 23. Como se muestra en este ejemplo,
cuando se utilizan las directivas INCLUDE entonces se generará un archivo
formateado correspondiente con cada archivo PSM fuente.
Entonces, siempre que su programa pueda caber en el rango de
direcciones disponible (por defecto es 4K pero puede utilizar la opción '-c'
cuando invoque al ensamblador para especificar una memoria más
pequeña), el ensamblador le dirá la última dirección ocupada y le indicará
el tamaño nominal de memoria de programa requerido. Aquí es donde
puede que necesite revisar su código y ajustar cualquier directiva
ADDRESS para que su programa quepa en una memoria de programa
más pequeña.

Tras un ensamblaje correcto, siempre se generará un fichero LOG y un


fichero HEX. El archivo de registro le proporciona un informe detallado que
muestra cómo se ha interpretado su archivo PSM y las direcciones y op-
codes asignados a cada instrucción (véase la página siguiente). El fichero
HEX es una simple lista hexadecimal de los 4096 op-codes definidos por tu
programa (todas las posiciones no definidas son cero) y es principalmente
para su uso con la utilidad JTAG Loader durante el desarrollo.
Por último, el ensamblador tiene la capacidad de generar un archivo VHDL
o Verilog que define la memoria de programa que necesitas para sintetizar
tu diseño de hardware. El archivo VHDL o Verilog describe las BRAM
preinicializadas con tu programa.

IMPORTANTE - El ensamblador sólo generará un archivo VHDL o Verilog


cuando haya una plantilla 'ROM_form.vhd' o 'ROM_form.v'
correspondiente en el mismo directorio que el archivo PSM de nivel
superior. Si se proporcionan ambas plantillas, se generarán archivos
Página Copyright 2010-2014 Xilinx
VHDL y Verilog.
Sugerencia - El archivo por defecto 'ROM_form.vhd' es una copia renombrada
del archivo llamado 'ROM_form_JTAGLoader_14March13.vhd' también incluido
en el archivo ZIP.

Página Copyright 2010-2014 Xilinx


El archivo de registro del ensamblador ('.log')
Este archivo 'LOG' no debería ser algo que necesites mirar muy a menudo, pero puede ser una referencia útil cuando estás depurando un sistema o tu
código, especialmente cuando estás analizando la interacción con el diseño hardware en un simulador HDL o en hardware real con ChipScope, etc.
Fecha de la asamblea: 19 Abr 2012 Este archivo comienza con un encabezado que incluye una marca de fecha y hora para
Marca de tiempo de montaje: ayudarle a realizar un seguimiento de sus iteraciones de código y saber qué programa está
16:02:20
utilizando
Cada vez que el ensamblador ha resuelto el valor de un operando se
La parte principal del archivo de registro muestra su
muestra entre corchetes, como referencia, la forma en que usted
programa y las direcciones y op-codes de cada
definió originalmente dicho operando. Por ejemplo...
instrucción.
Código de Instruccion Este código PSM es adecuado SALIDA sF[contador], 02[puerto_X]
es
dirección para el
000 ;
hardware que se muestra en la El registro 'sF' fue definido por el nombre 'counter' y la dirección port_id
página 72. '02' fue definida por la directiva CONSTANT 'X_port'.
nombre Valor
CONSTANTE
Tras el listado del programa en timestamp_horas 16'd
ensamblador, siguen listas de timestamp_minutes 16'd
todas las constantes, tablas, timestamp_seconds 54'd
cadenas y etiquetas de línea datestamp_year 12'd
datestamp_mes 4'd
definidas en su programa o por datestamp_day 19'd
el ensamblador. Puerto_A 00
B_port 01
Estas listas pueden ser C_port 02
D_port 03
especialmente útiles a la hora de W_port 01
confirmar la asignación de X_port 02
puertos con el diseño del Y_port 04
hardware. Z_port 08

No se han definido
Aunque no se muestra en este
ejemplo, las listas también TABLAS Lista de
identifican el archivo PSM en el
cadenas
STRING de texto Cadena
que se definió el elemento. Esto nombre
ayuda cuando se utilizan KCPSM6_version$ "v2.00"
directivas INCLUDE. datestamp$ "19 abr
2012"
timestamp$ "16:16:54"
Página Copyright 2010-2014 Xilinx
Sugerencia
00B 22000 - Las constantes y cadenas
JUMP 'datestamp' y 'timestamp', junto con HWBUILD, proporcionan todo lo necesario para
000[start]
implementar un esquema de informes de versiones para las unidades de producción, así como para realizar un seguimiento
a lo largo del desarrollo.

Página Copyright 2010-2014 Xilinx


Cada línea de tu archivo PSM debe seguir la siguiente sintaxis básica. No te preocupes demasiado por que todo esté perfecto u ordenado porque el
ensamblador se ocupará de cosas como los espacios adicionales y es muy tolerante con los caracteres en mayúsculas o minúsculas excepto cuando
realmente importa. Si haces algo mal, el ensamblador te mostrará lo que no le gusta y te dará consejos para ayudarte a corregirlo. KCPSM6 escribe un
archivo FMT bien formateado para que lo adoptes.

etiqueta: instrucción operando1, operando2 ;


comentario
A cualquier línea se le CALL, así como con Cualquiera de las instrucciones Todas las instrucciones y Las instrucciones y directivas
puede asignar una etiqueta los atributos 'lower y KCPSM6 o una directiva del directivas excepto RETURN que requieren un segundo
que se asociará a una 'upper para definir ensamblador. Se aceptan tienen al menos un operando y operando deben separarse del
dirección. Cuando se define constantes para su mayúsculas o minúsculas. éste debe estar separado de la primero mediante una coma ','.
una etiqueta, debe ir uso en otras instrucción por al menos un (los espacios son sólo de
seguida de dos puntos ':' . instrucciones. espacio. formato).
Una etiqueta distingue entre Los nombres de registro por defecto se representan mediante 'sX' o 'sY' y pueden ser
mayúsculas y minúsculas y cualquiera de los siguientes... 's0', 's1', 's2', 's3', 's4', 's5', 's6', 's7', 's8', 's9', 'sA', 'sB', 'sC',
puede ser cualquier número 'sD', 'sE', 'sF'.
de los caracteres estándar El ensamblador aceptará mayúsculas y minúsculas, por ejemplo, 'sb', 'SB' y 'Sb' son también
'a' a 'z' , 'A' a 'Z', '0' a '9'' y '_' Los valores constantes se representan mediante "aaa", "kk", "ss", "p" y "pp".
'sB'.
(guión bajo) pero no debe Cada carácter representa el requisito de un dígito hexadecimal para definir una dirección,
ser un nombre que pueda constante o puerto. Así por ejemplo 'kk' es cualquier valor en el rango '00' a 'FF'
confundirse con un valor hexadecimal.
hexadecimal. Los valores hexadecimales son los predeterminados y pueden especificarse en mayúsculas
o minúsculas, por ejemplo, "6d" o "6D".
Una etiqueta se puede
Los atributos "d" y "b" permiten definir valores decimales y binarios.
utilizar en cualquier parte
Por ejemplo, 109'd y 01101101'b equivalen a '6D' hexadecimal.
del programa para definir la
También sólo para constantes 'kk'...
dirección de destino para Se puede asignar el equivalente ASCII de un carácter, por ejemplo, "n" es lo mismo
una instrucción JUMP o que '6D' Los 8 bits inferiores de una dirección se pueden identificar utilizando
Página Copyright 2010-2014 Xilinx
label'lower.
Todo lo que siga a un comentario vacío (sólo un contengan una instrucción
punto y coma ';' será Sugerencia - El punto y coma) para Las líneas que sólo se formatearán en una
tratado como un ensamblador conservar una línea en contengan comentarios se columna a la derecha de la

Sintaxis PSM
comentario e ignorado ignora las líneas blanco en los archivos FMT formatearán en línea con las instrucción más larga. Se
por el ensamblador. vacías, así que y LOG. instrucciones. Los ve bien ☺
utilice un comentarios en líneas que
Las directivas del ensamblador siguen la misma sintaxis básica, pero sólo se utilizan para dirigir al ensamblador y facilitar la escritura y comprensión del
código.
DEFAULT_JUMP
INCLUDE aaa / CONSTANTE
"fichero.psm" nombre, kk / DIRECCIÓN proporciona
NOTA - 'all_kcpsm6_syntax.psm' aaa / NAMEREG nombreantiguo,
un archivo nombrenuevo
PSM (aunque / CADENA
no es nombre$,
un programa "texto"
real) que/ describe
TABLA nombre#, [kk,kk,kk,..]
con más
/ INST hhhhhh detalle todas las directivas y tiene ejemplos de toda la sintaxis soportada. Dado que es un archivo PSM válido puedes
ensamblarlo y luego mirar también los archivos FMT y LOG que genera KCPSM6.

Página Copyright 2010-2014 Xilinx


Los registros y la Directiva NAMEREG
En general, el KCPSM6 puede acceder a 16 registros de propósito general a los que se asignan los nombres 16 Registros
predeterminados de 's0' a 'sF'. No hay absolutamente ninguna restricción sobre qué registro o combinación de Todos los fines
registros se pueden especificar como operandos 'sX' o 'sY' en cualquiera de las instrucciones que trabajan con generales Todos los 8
registros. Esto le proporciona total libertad para asignar los registros como desee. Si se tiene cuidado con la -bits
asignación de registros a diferentes tareas, a menudo se evitará la necesidad de "barajar" demasiado los datos
(como suele ocurrir cuando se utiliza un procesador con una arquitectura basada en acumuladores). sF

El ensamblador KCPSM6 es capaz de identificar el nombre por defecto de un registro independientemente de la sE


mezcla de caracteres en mayúsculas y minúsculas que utilices para describirlo, pero siempre lo convertirá a la 's'
minúscula seguida de un dígito hexadecimal en mayúsculas cuando escriba los archivos FMT y LOG. Por ejemplo, sD
'S4' se interpretará como el nombre de registro por defecto 's4'. Del mismo modo, 'sd', 'Sd' y 'SD' se interpretarán
sC
como el nombre de registro por defecto 'sD'. En otras palabras, el ensamblador te permite concentrarte en escribir tu
código sin tener que ser tan preciso con la sintaxis y el formato. sB
Directiva NAMEREG sA

La directiva NAMEREG es una función opcional que puede ayudarte a saber qué datos esperas que contenga un s9
determinado registro. Antes de la directiva NAMEREG, un registro tendrá un nombre por defecto como 'sB'. Una vez
renombrado, sólo el nuevo nombre identificará el registro y ese nombre distingue entre mayúsculas y minúsculas s8
exactamente como usted lo definió. Cambiar el nombre no tiene ningún efecto en el contenido del registro o en cómo
se puede utilizar.
SUBvelocidad, 01
ADD sB, 42 ;
; Velocidad NAMEREG, sB
NAMEREG sB, Estado ;
; CARGAR sB, 19
;
INPUT Estado,
flags_port COMPARE
Estado, 12
;
NAMEREG Estado,
velocidad
;

Página Copyright 2010-2014 Xilinx


a 'a' a la 'z', de la 'A' a la 'Z' y el guión bajo '_'
(
El nombre de registro por si
n6 espacios). Puede tener cualquier longitud, pero no debe ser un nombre que
defecto se aplica antes de la p
ueda5 confundirse con otra cosa, comos7 una etiqueta de línea o un valor
directiva NAMEREG.
hexadecimal.
E Siguiendo la directiva NAMEREG, sólo es válido el nuevo nombre y que s4
l distingue entre mayúsculas y minúsculas. En este caso, "sB" ya no se reconocerá.
s3
n La directiva NAMEREG puede utilizarse para cambiar el nombre de un registro s2
u de nuevo. Sólo el nuevo nombre es válido en el código que sigue. En función de
e
tu forma de pensar esto es o útil o algo a evitar! ☺ s1
v
o s0
NAMEREG también puede utilizarse para restaurar el registro por defecto apropiado
n y también se aplican las reglas normales de insensibilidad a mayúsculas y minúsculas.
o
m
b
r
e

s
ó
l
o

p
u
e
d
e

c
o
n
t
e
n
e
r

d
e

l
Página Copyright 2010-2014 Xilinx
aaa : Dirección de 12 bits 000
a FFF kk : Constante de 8

Juego de instrucciones bits 00 a FF pp : ID de


puerto de 8 bits 00 a FF
p : ID de puerto de 4 bits 0 a F

KCPSM6 ss : 8-bit scratch pad ubicación 00 a FF


x : Registro dentro del banco s0 a sF
y : Registro dentro del banco s0 a sF

Página Opcode Instrucción Página Opcode Instrucción Página Opcode Instrucción


Carga del registro Desplazamiento y Gestión de interrupciones
rotación
55 00xy0 CARGA sX, sY 67 14x06 SL0 sX 83 28000 DESACTIVAR
R INTERRUPCIÓN
55 01xkk CARGA sX, kk 67 14x07 SL1 sX 83 28001 ACTIVAR
R INTERRUPCIÓN
71 16xy0 ESTRE sX, sY 67 14x04 SLX sX 84 29000 RETURNI
LLA DESACTIVAR
71 17xkk ESTRE sX, kk 67 14x00 SLA sX 84 29001 RETURNI HABILITAR
LLA
0Cxy0TEST sX, sY 67 14x02RL sX
Lógica 63
0DxkkTEST sX, kk 68 14x0ESR0 sX
63
56 02xy0y sX, 68 14x0FSR1 sX
sY 68 14x0ASRX sX
56 03xkkY sX, kk 68 14x08SRA sX
57 04xy0OR sX, sY 68 14x0CRR sX
57 05xkkOR sX, kk
58 06xy0XOR sX, sY Selección del banco de registros
58 07xkkXOR sX, kk 70 37000 REGBANK A
Aritmética 70 37001 REGBANK B

59 10xy0ADD sX, sY Entrada y salida


59 11xkkADD sX, kk
73 08xy0INPUT sX, (sY)
60 12xy0ADDCY sX, sY
73 09xppINPUT sX, pp
60 13xkkADDCY sX, kk
74 2Cxy0OUTPUT sX,(sY)
61 18xy0SUB sX, sY
74 2DxppOUTPUT sX, pp
61 19xkkSUB sX, kk
78 2BkkpOUTPUTK kk, p
62 1Axy0SUBCY sX, sY
62 1BxkkSUBCY
Memoria del bloc de notas
sX, kk
Probar y comparar (64, 128 o 256 bytes)
Página Copyright 2010-2014 Xilinx
Subrutinas aaa
94 24xy0CALL@ (sX, sY)
Saltar 20aaaCALL aaa
92 96 25000 DEVOLVER
87 22aaa SALTO aaa 93 30aaaCALL Z, 97 31000 DEVOLVE Z
88 32aaa SALTO Z, aaa aaa R
88 36aaa SALTO NZ, aaa 93 34aaaCALL NZ, 97 35000 DEVOLVE NZ
88 3Aaaa SALTO C, aaa aaa R
64 0Exy0 TESTCY sX, sY 93
81 2Exy0 38aaaCALL
GUARDAR C, 97 39000 DEVOLVE C
88 3Eaaa SALTO NC, aaa 98 21xkkLOAD&RETURN sX, kk
64 0Fxkk TESTCY sX, kk aaa sX,(sY) R
89 26xy0 JUMP@ (sX, sY) 93 3CaaaCALL NC,
65 1Cxy0 COMPARAR sX, sY 81 2Fxss ALMACENAR sX, 3D000
97 Control DEVOLVE NC
de versiones
65 1Dxkk COMPARAR sX, kk ss R
66 1Exy0 COMPARACIÓN sX, 82 0Axy0 FETCH sX, (sY) 101 14x80HWBUILD sX
sY 82 0Bxss FETCH sX, ss
66 1Fxkk COMPARACIÓN sX,
kk

Página Copyright 2010-2014 Xilinx


CARGAR sX
, kk LOAD sX
, sY
Las instrucciones 'LOAD' proporcionan una forma sencilla de definir el contenido de cualquier registro (sX). El valor cargado en un registro puede ser un valor
fijo (kk) o puede copiarse el valor contenido en cualquier registro (sY). Los estados de la bandera cero (Z) y la bandera de acarreo (C) no se verán afectados.

sX kk
CARGA sX, kk sX = kk

C Sin
cambios
Z Sin
cambios
CARGA sX, sY sX = kY
sX sY

C Sin
Ejemplos
cambios
LOAD sA, 8E El ensamblador KCPSM6 permite valores constantes en todas las instrucciones que requieren que se definan en
LOAD s4, 42'd Z Sin binario o utilizando un único carácter que se convierte a su valor equivalente ASCII.
hexadecimal (por defecto), decimal,
LOAD s9, 10001110'b cambios
Una vez ejecutado este ejemplo....
LOAD s6, "k"
s7', 's9' y 'sA' contendrán 8E hex. sA'
LOAD s7, sA
contendrá 2A hex.
LOAD s5, CR
s6' contendrá 77 hex (el código ASCII para 'k') y 's5' contendrá 0D hex (el código ASCII para Carriage Return) .

Sugerencia - Cargar un registro consigo mismo no tiene otro efecto que el de tardar 2 ciclos de reloj, pero puede ser una forma útil de crear un retardo
conocido.

Notas
sX' y 'sY' definen cualquiera de los 16 registros en el rango de 's0' a 'sF' en el banco de registro activo. Consulte la sección "Uso de los bancos de
registros" para ver cómo cambiar entre los bancos de registros "A" y "B" y las técnicas para copiar valores de los registros de un banco a los registros del
otro.

Página Copyright 2010-2014 Xilinx


La instrucción op-code 00000 hex fue específicamente asignada para ser la instrucción 'LOAD s0, s0'. De esta forma, el valor por defecto (cero) de cualquier
contenido de memoria de programa no utilizado tendrá el mínimo efecto en caso de que un programa incorrecto provoque la ejecución de estas ubicaciones no
definidas.

Página Copyright 2010-2014 Xilinx


AND sX , kk
AND sX , sY
Las instrucciones 'AND' realizan la operación lógica AND a nivel de bits.

El primer operando debe especificar un registro 'sX' cuyo valor proporciona una entrada a la operación AND y en el que se devuelve el
resultado. El segundo operando define la segunda entrada de la operación AND y puede ser una constante de 8 bits 'kk' o un registro 'sY'.
El indicador de cero (Z) se activará si los 8 bits del resultado devuelto a 'sX'
son cero. La bandera de acarreo (C) se borrará (C=0) en todos los casos.
s Y o kk 7 6 5 4 3 2 1 0

AND s X , kk sX = sX Y kk

AND sX, sY sX = sX Y sY

C sX 7 6 5 4 3 2 1 0
'0'

Ejemplos
= '00' ? Referenci
CARGAR sA, CA = 1 1 0 0 1 0 1 0
sA = 42, Z=0, C=0. a
CA Y sA, 53 53 = 0 1 0 1 0 0 1 1 Z
CA Y 53 = 0 1 0 0 0 0 1 0 = 42
A B AYB
LOAD sA, CA CA = 1 1 0 0 1 0 1 0 0 0 0
LOAD sB, 14 sA = 00, Z=1, C=0. 14 = 0 0 0 1 0 1 0 0 0 1 0
AND sA, sB CA Y 14 = 0 0 0 0 0 0 0 0 = 00 1 0 0
1 1 1
AND s5, 00001111'b Sugerencia - Esto borrará el nibble superior de 's5' y podría utilizarse para convertir los
caracteres ASCII '0' a '9' (30 a 39 hex) en sus valores numéricos equivalentes (00 a 09
hex).

CONSTANTE bit2, 00000100'b Sugerencia - 'AND' proporciona una manera de borrar bits a '0'. En este ejemplo se borra el bit2 del registro s0.
AND s0, ~bit2 Observe cómo todos los bits de una CONSTANTE pueden invertirse localmente utilizando ~ antes del
nombre. Por lo tanto la constante realmente aplicada en este caso es 11111011'b. (ver 'OR' para fijar
Y s5, FF bits).
Página Copyright 2010-2014 Xilinx
Sugerencia de codificación - Borra el indicador de acarreo sin cambiar el contenido del registro (véase también HWBUILD).

Página Copyright 2010-2014 Xilinx


OR sX, kk
OR sX, sY
Las instrucciones 'OR' realizan la operación lógica OR a nivel de bits.

El primer operando debe especificar un registro 'sX' cuyo valor proporciona una entrada a la operación OR y en el que se devuelve el
resultado. El segundo operando define la segunda entrada de la operación OR y puede ser una constante de 8 bits 'kk' o un registro 'sY'.
El indicador de cero (Z) se activará si los 8 bits del resultado devuelto a 'sX'
son cero. La bandera de acarreo (C) se borrará (C=0) en todos los casos.
s Y o kk 7 6 5 4 3 2 1 0

OR sX, kk sX = sX O kk

OR s X , sY sX = sX O sY

C sX 7 6 5 4 3 2 1 0
'0'

Ejemplos
= '00' ?
Referencia
LOAD sA, CA CA = 1 1 0 0 1 0 1 0 Z
OR sA, 53 sA = DB, Z=0, C=0. 53 = 0 1 0 1 0 0 1 1
CA O 53 = 1 1 0 1 1 0 1 1 = DB A B AOB
0 0 0
LOAD sA, CA CA = 1 1 0 0 1 0 1 0
sA = DE, Z=0, C=0. 0 1 1
LOAD sB, 14 14 = 0 0 0 1 0 1 0 0
1 0 1
OR sA, sB CA O 14 = 1 1 0 1 1 1 1 0 = DE
1 1 1
Sugerencia - Esto establece 2 bits en el nibble superior de 's5' y podría ser utilizado para convertir el numérico
OR s5, 00110000'b
valores 00 a 09 hex en sus caracteres equivalentes ASCII '0' a '9' (30 a 39 hex).

CONSTANTE bit2, 00000100'b Sugerencia - 'OR' permite poner bits a '1'. La directiva CONSTANT proporciona una forma cómoda de nombrar
OR s0, bit2 los bits que desee controlar de esta manera (véase "AND" para borrar bits).

Página Copyright 2010-2014 Xilinx


XOR sX , kk
XOR sX , sY
Las instrucciones 'XOR' realizan la operación lógica bit-ise exclusive-OR.

El primer operando debe especificar un registro 'sX' cuyo valor proporciona una entrada a la operación XOR y en el que se devuelve el
resultado. El segundo operando define la segunda entrada de la operación XOR y puede ser una constante de 8 bits 'kk' o un registro
'sY'.
El indicador de cero (Z) se activará si los 8 bits del resultado devuelto a 'sX'
son cero. La bandera de acarreo (C) se borrará (C=0) en todos los casos.
s Y o kk 7 6 5 4 3 2 1 0

XOR sX, kk sX = sX XOR kk

XOR sX, sY sX = sX XOR sY

C sX 7 6 5 4 3 2 1 0
'0'

Ejemplos
= '00' ?
Referenci
CARGA sA, CA CA a
sA = 99, Z=0, C=0. = 1 1 0 0 1 0 1 0 Z
XOR sA, 53 53 = 0 1 0 1 0 0 1 1
CA XOR 53 = 1 0 0 1 1 0 0 1 = 99 A B A XOR B
0 0 0
CARGA sA, CA CA = 1 1 0 0 1 0 1 0
0 1 1
CARGAR sB, 14 sA = DE, Z=0, C=0. 14 = 0 0 0 1 0 1 0 0
1 0 1
XOR sA, sB CA XOR 14 = 1 1 0 1 1 1 1 0 = DE
1 1 0

CONSTANTE estroboscópica, Sugerencia - La instrucción XOR puede utilizarse para conmutar el estado de los bits de un registro. En
00000001'b este ejemplo, el bit menos significativo de 's0' se conmuta dos veces y se envía a un puerto.
XOR s0, strobe Asumiendo que el LSB era '0' al principio, esto habrá generado un pulso positivo ('1') en el LSB del
OUTPUT s0, ctrl_port puerto de salida, mientras que el resto de bits no se verán afectados. La directiva CONSTANT
XOR s0, strobe
Página s0, 0 ctrl_port
OUTPUT Copyright 2010-2014 Xilinx
proporciona una forma conveniente de nombrar los bits que se desea controlar de esta manera.

Página Copyright 2010-2014 Xilinx


ADD sX , kk
ADD sX , sY
Las instrucciones 'ADD' realizan la suma aritmética de dos valores de 8 bits y establecen las banderas de acarreo y cero en función del resultado.

El primer operando debe especificar un registro 'sX' cuyo valor proporciona una entrada a la función de suma y en el que se devuelve el
resultado. El segundo operando define la segunda entrada de la suma y puede ser una constante de 8 bits 'kk' o un registro 'sY'.
La bandera cero (Z) se activará si el resultado de 8 bits devuelto a 'sX'
es cero. La bandera de acarreo (C) se activará si la suma resulta en
un desbordamiento.

sX
ADD sX, kk sX = sX + kk
s Y o kk
ADD sX, sY sX = sX + sY

Fijar si resultado sX
> 'FF C

= '00' ?
Z

Ejemplos

LOAD sA, 8E
ADD sA, 43 8E + 43 = D1sA = D1 que no es cero (Z=0) y sin desbordamiento (C=0).

LOAD sA, 142'd


ADD sA, sA 142 + 142 = 284284 = 256 + 28 por lo tanto sA =28 (1C hex) que no es cero (Z=0) y ha habido un desbordamiento
(C=1).

Página Copyright 2010-2014 Xilinx


LOAD sA, 8E
ADD sA, 728E + 72 = 100sA = 00 que es cero (Z=1) pero también hubo un desbordamiento que hizo que esto sucediera (C=1).

Página Copyright 2010-2014 Xilinx


ADDCY sX, kk
ADDCY sX, sY
Las instrucciones 'ADDCY' están pensadas principalmente como una extensión de las instrucciones básicas 'ADD' para soportar la suma aritmética de
valores de más de 8 bits. La principal diferencia con respecto a las instrucciones ADD es que las banderas de cero y acarreo también se utilizan como
entradas de la función de suma y pueden influir tanto en el resultado de 8 bits como en los nuevos estados de las banderas. Aunque cada registro sólo
contiene un valor de 8 bits, se puede utilizar cualquier combinación de registros para contener valores mayores segmentados en bytes. Por ejemplo, un
valor de 32 bits puede almacenarse en 4 registros. Aunque no hay ninguna restricción sobre qué registros, y ninguna manera formal de describir la
asignación, es una práctica común asignar registros adyacentes y referirse a ellos como un "conjunto de registros" como [sD, sC, sB, sA].

El primer operando debe especificar un registro 'sX' cuyo valor proporciona una entrada a la función de suma y en el que se devuelve el
resultado. El segundo operando define la segunda entrada de la suma y puede ser una constante de 8 bits 'kk' o un registro 'sY'.
El indicador de cero (Z) se activará si el resultado de 8 bits devuelto a 'sX' es cero y el indicador de cero se activó antes de
la instrucción ADDCY. El indicador de acarreo (C) se activará si la suma produce un desbordamiento.
sX

ADDCY sX, kk sX = sX + kk + C s Y o kk
k k k k k k k k
ADDCY sX, sY sX = sX + sY + C Transferencia de
C
la operación anterior
Fijar si resultado sX
Ejemplos > 'FF C

La observación clave que hay que hacer, como se ilustra en = '00' ?


estos ejemplos, es que las banderas de acarreo y cero
reflejan el resultado completo de una suma multibyte. En Z Y Z=1 ? Cero de la
concreto, el indicador cero sólo se activa si el resultado Z operación anterior
completo de la suma multibyte es cero y no se basa
únicamente en el resultado de 8 bits de la operación
ADDCY final.

[sB, sA] = A2 7B 7B + 1A = 95sA = 95, Z=0, C=0.


LOAD sA, 7B
LOAD sB, A2 + 5E 1A = 10095 A2 + 5E + 0 = 100sB = 00, Z=0, C=1.
ADD sA, 85
ADDCY sB, 5D
Página Copyright 2010-2014 Xilinx
[sB, sA] = A2 7B
LOAD sA, 7B
+ 5D 85 = 10000 LOAD sB, A2
ADD sA, 85
7B + 85 = 100sA = 00, Z=1, C=1.
ADDCY sB, 5D
A2 + 5D + 1 = 100sB = 00, Z=1,
C=1.

Página Copyright 2010-2014 Xilinx


SUB sX, kk
SUB sX, sY
Las instrucciones 'SUB' realizan la resta aritmética de dos valores de 8 bits y establecen las banderas de acarreo y cero según el resultado.

El primer operando debe especificar un registro 'sX' del que se restará el segundo operando y al que se devolverá el resultado. El
segundo operando define el valor a restar del primer operando y puede ser una constante de 8 bits 'kk' o un registro 'sY'. La bandera
cero (Z) se activará si el resultado de 8 bits devuelto a 'sX' es cero.
La bandera de carry (C) se activará si el resultado de la resta es negativo. Por lo tanto, la bandera de carry representa un desbordamiento o un "préstamo"
para completar la operación.

sX
SUB sX, kk sX = sX - kk
s Y o kk
SUB sX, sY sX = sX - sY

Fijar si resultado sX
< '00' C

= '00' ?
Z
Ejemplos

LOAD sA, 8E
SUB sA, 43 8E - 43 = 4BsA = 4B que no es cero (Z=0) y sin desbordamiento (C=0).

LOAD sA, 8E
ADD sA, sA 8E - 8E = 00sA = 00 que es cero (Z=1) pero todavía no había desbordamiento (C=0).

LOAD sA, 8E 8E - B5 = 1D9sA = D9 que no es cero (Z=0) pero hubo un desbordamiento (C=1).
SUB sA, B5 Esto equivale a 142 - 181 = -39, donde D9 hexadecimal es la representación del complemento a dos de
-39. Sin embargo, es responsabilidad del usuario implementar e interpretar los valores y operaciones

Página Copyright 2010-2014 Xilinx


aritméticas con signo.

Página Copyright 2010-2014 Xilinx


SUBCY sX, kk
SUBCY sX, sY
Las instrucciones 'SUBCY' están pensadas principalmente como una extensión de las instrucciones básicas 'SUB' para soportar la sustracción aritmética
de valores de más de 8 bits. La diferencia clave con las instrucciones SUB es que las banderas de cero y acarreo también se utilizan como entradas de la
función de resta y pueden influir tanto en el resultado de 8 bits como en los nuevos estados de las banderas. Aunque cada registro sólo contiene un valor
de 8 bits, se puede utilizar cualquier combinación de registros para contener valores mayores segmentados en bytes. Por ejemplo, un valor de 32 bits
puede almacenarse en 4 registros. Aunque no hay ninguna restricción sobre qué registros, y ninguna manera formal de describir la asignación, es una
práctica común asignar registros adyacentes y referirse a ellos como un "conjunto de registros" como [sD, sC, sB, sA].

El primer operando debe especificar un registro 'sX' del que se restará el segundo operando y la bandera de acarreo y al que se devuelve el
resultado. El segundo operando define el valor a restar del primer operando y puede ser una constante de 8 bits 'kk' o un registro 'sY'.
La bandera cero (Z) se activará si el resultado de 8 bits devuelto a 'sX' es cero y la bandera cero se activó antes de la instrucción SUBCY.
La bandera de carry (C) se activará si el resultado de la resta es negativo. Por lo tanto, la bandera de carry representa un desbordamiento o un "préstamo"
para completar la operación.
sX

SUBCY sX, kk sX = sX - kk - C s Y o kk
k k k k k k k k
SUBCY sX, s Y sX = sX - sY - C Transferencia de
C
la operación anterior
Fijar si resultado sX
Ejemplos < '00' C

La observación clave que hay que hacer, como se ilustra = '00' ?


en estos ejemplos, es que las banderas de acarreo y cero
reflejan el resultado completo de una resta multibyte. En Z Y Z=1 ? Cero de la
concreto, el indicador cero sólo se activa si el resultado Z operación anterior
completo de la resta multibyte es cero y no se basa
únicamente en el resultado de 8 bits de la operación
SUBCY final.

[sB, sA] = A2 7B
LOAD sA, 7B 7B - B9(-)C2 = C2, Z=0, C=1. A2 - A1 - 1 =
LOAD sB, A2 - A1 B9 = 00C2
SUB Página
sA, B9
Copyright 2010-2014 Xilinx
SUBCY sB, A1
00sB = 00, Z=0, [sB, sA] = A2 7B
C=0. LOAD sA, 7B
LOAD sB, A2 - A2 7B = 0000
SUB sA, sA
7B - 7B00 = 00,Z = 1 , C=0. A2 -
SUBCY sB, sB
A20 = 00 = 00, Z=1, C=0.

Página Copyright 2010-2014 Xilinx


TEST sX, kk
TEST sX, sY
Las instrucciones "TEST" son similares a las instrucciones "AND" en el sentido de que se realiza una operación lógica AND de bits. Sin embargo, el
resultado real se descarta y sólo se actualizan los indicadores para reflejar los 8 bits temporales. La instrucción "TEST" también informa del OR exclusivo
del resultado temporal, que puede utilizarse para calcular la "paridad impar" de un valor.

El primer operando debe especificar un registro 'sX' cuyo valor proporciona una entrada a la operación AND (sX no se verá afectado por la
operación). El segundo operando define la segunda entrada de la operación AND y puede ser una constante de 8 bits "kk" o un registro "sY".
El indicador cero (Z) se activará si los 8 bits del resultado temporal son cero.
La bandera de acarreo (C) se activará si el resultado temporal contiene un número impar de bits con valor '1' (el OR exclusivo del resultado temporal de 8 bits).

PRUEBA sX, kk temp = sX AND kk sX 7 6 5 4 3 2 1 0

TEST sX, sYtemp = sX AND


s Y o kk 7 6 5 4 3 2 1 0
sY Sugerencias

Es típico pensar que 'sX' contiene la información que se va a


comprobar y que 'sY' o 'kk' actúan como máscara de bits para
seleccionar sólo los bits que se van a comprobar.
temp 7 6 5 4 3 2 1 0
Para comprobar un solo bit, el valor de 'kk' se describe mejor
utilizando un formato binario como 00100000'b que enviará el
texto al bit 5 (equivalente a 20 hex). La bandera 'C' se activará
si el bit correspondiente en 'sX' es '1' y la bandera 'Z' se = '00' ?
activará si el bit probado es '0'. Z

Utilice un valor de máscara de kk = FF para calcular la ¿Raro


paridad impar del byte entero contenido en 'sX'. C ?
Ejemplos La paridad es extraña.
CARGA sA, CA
TEST sA, 01000000'b Z=0, C=1 (impar).

LOAD sA, 51
TEST sA, FF Z=0, C=1.

Página Copyright 2010-2014 Xilinx


CA = 1 1 0 0 1 0 1 0
40 = 0 1 0 0 0 0 0 0
CA Y 40 = 0 1 0 0 0 0 0 0 = 40

51 = 0 1 0 1 0 0 0 1 Sugerencia - Las instrucciones de desplazamiento


'SLA' y 'SRA' y las instrucciones de desplazamiento
FF = 1 1 1 1 1 1 1 1 Las instrucciones ADDCY y SUBCY pueden
utilizarse para
51 Y FF = 0 1 0 1 0 0 0 1 = 51 mover el valor de la bandera de acarreo a un
registro.

Página Copyright 2010-2014 Xilinx


TESTCY sX, kk
TESTCY sX, sY
Las instrucciones 'TESTCY' están pensadas principalmente como una extensión de las instrucciones básicas 'TEST' para soportar la comprobación y el
cálculo de paridad impar de valores de más de 8 bits. La diferencia clave con las instrucciones TEST es que las banderas de cero y acarreo también se
utilizan como entradas que pueden influir en los nuevos estados de las banderas. Aunque cada registro sólo contiene un valor de 8 bits, se puede utilizar
cualquier combinación de registros para contener valores mayores segmentados en bytes. Por ejemplo, un valor de 32 bits puede almacenarse en 4
registros. Aunque no hay ninguna restricción sobre qué registros, y ninguna manera formal de describir la asignación, es una práctica común asignar
registros adyacentes y referirse a ellos como un "conjunto de registros" como [sD, sC, sB, sA].

El primer operando debe especificar un registro 'sX' cuyo valor proporciona una entrada a la operación AND (sX no se verá afectado por la
operación). El segundo operando define la segunda entrada de la operación AND y puede ser una constante de 8 bits "kk" o un registro "sY".
La bandera cero (Z) se activará si los 8 bits del resultado temporal son cero y la bandera cero se activó antes de la instrucción TESTCY.
La bandera de acarreo (C) se activará si el resultado temporal junto con el estado previo de la bandera de acarreo contiene un número impar de bits puestos a
'1'.

PRUEBA sX, kk temp = sX AND kk sX 7 6 5 4 3 2 1 0

TEST sX, sY temp = sX AND sY


s Y o kk 7 6 5 4 3 2 1 0

El significado de las banderas 'C' y 'Z' es el mismo después


de una combinación de instrucciones TEST y TESTCY
utilizadas para comprobar y calcular la paridad impar de un
valor multibyte que después de una única operación TEST de
8 bits. temp 7 6 5 4 3 2 1 0

Ejemplos

LOAD sA, CA = '00' ?


LOAD sB, 52 [sB, sA] = 11001010 0101001
Z AND Z=1 ? Cero de
TEST sA, FF Z operación anterior
TESTCY sB, FF 7 bits en total son '1' por lo que la paridad es impar. Z=0, C=1.

¿Raro
C ? Llevar de
C operación anterior
Página Copyright 2010-2014 Xilinx
CARGA sA, CA
[sB, sA] = 11001010 0101001
CARGAR sB, 52
TEST sA, 00000100'b
Tanto el bit13 como el bit3 de la palabra de 16
TESTCY sB, 00100000'b
bits son '0'. Z=1, C=0 (par).

Página Copyright 2010-2014 Xilinx


COMPARAR sX, kk
COMPARAR sX, sY
Las instrucciones "COMPARE" realizan la resta aritmética de dos valores de 8 bits, pero el resultado real se descarta y sólo se conservan las banderas de
acarreo y cero.
actualizado en función del resultado temporal.

El primer operando debe especificar un registro 'sX' del que se restará el segundo operando (el valor de sX no se verá afectado por la operación). El
segundo operando define el valor a restar del primer operando y puede ser una constante de 8 bits 'kk' o un registro 'sY'.
El indicador cero (Z) se activará si el resultado temporal de 8 bits es cero y ambos operandos son iguales o "coincidentes".
La bandera de acarreo (C) se activará si el resultado temporal de la resta es negativo y, por tanto, indica cuando 'sX' es menor que el segundo operando.

sX
COMPARAR sX, kk temp = sX - kk
Estados de
abanderamien Comparación COMPARAR sX, sY temp = sX - sY s Y o kk
to
Z C
Fijar si temp < temp
0 0 sX > kk o sX > s Y
'00' C
x 1 sX < kk o sX < s Y

1 x sX = kk o sX = s Y
= '00' ?
Z
Ejemplos
Sugerencias
LOAD sA, 8E
COMPARE sA, 8E Los valores son iguales, Utilice 'Z' para determinar cuándo los valores son iguales o 'coinciden'.
JUMP Z, igual
Z=1, C=0. La bandera 'C' puede utilizarse para determinar cuándo sX es menor que el segundo
operando. Por lo tanto, también se puede utilizar para determinar cuando s X e s
m a y o r o igual que el segundo operando'. Así que cuando compare los contenidos
de dos registros asígnelos a 'sX' y 'sY' de tal forma que pueda usar 'C' para identificar
LOAD sA, 8E cual es menor. Esto evitará el requerimiento de probar ambas banderas 'C' y 'Z'.
COMPARE sA, 98 sA < 98, Z=0, C=1.
JUMP C, menor_que
Página Copyright 2010-2014 Xilinx
El
ensambla
dor
KSPSM6
permite
especifica
r
constante
s en
caractere
s
hexadeci
males,
decimales
y ASCII,
por
ejemplo
COMPAR
E s0, "Q"

Página Copyright 2010-2014 Xilinx


COMPARACIÓN sX,
kk COMPARACIÓN
Las instrucciones "COMPARECY" están pensadas principalmente como una extensión de las instrucciones básicas "COMPARE" para poder comparar
valores de más de 8 bits. La diferencia clave con las instrucciones COMPARE es que las banderas de cero y acarreo también se utilizan como entradas de

sX, sY
la resta utilizada para realizar la comparación y éstas pueden influir tanto en el resultado de 8 bits antes de ser descartado como en los nuevos estados de
las banderas. Aunque cada registro sólo contiene un valor de 8 bits, se puede utilizar cualquier combinación de registros para contener valores mayores
segmentados en bytes. Por ejemplo, un valor de 32 bits puede almacenarse en 4 registros. Aunque no hay ninguna restricción sobre qué registros, y
ninguna manera formal de describir la asignación, es una práctica común asignar registros adyacentes y referirse a ellos como un "conjunto de registros"
como [sD, sC, sB, sA].

El primer operando debe especificar un registro 'sX' del que se restarán el segundo operando y la bandera de acarreo (sX no se verá afectado por la
operación). El segundo operando define el valor a restar del primer operando y puede ser una constante de 8 bits 'kk' o un registro 'sY'.
El indicador de cero (Z) se activará si el resultado temporal de 8 bits es cero y el indicador de cero se activó antes de la instrucción
COMPARECY. La bandera de acarreo (C) se activará si el resultado
temporal de la resta es negativo. sX

COMPARACIÓN sX, kk temp = sX - kk - C s Y o kk


k k k k k k k k
COMPARACIÓN sX, s Y temp = sX - sY - C Transferencia de
C
la operación anterior
Fijar si temp < temp
Ejemplos
'00' C

El significado de las banderas "C" y "Z" es el mismo


después de una combinación de instrucciones COMPARE y = '00' ?
COMPARECY utilizada para comparar valores multibyte
que después de una sola operación COMPARE de 8 bits. Z Y Z=1 ? Cero de la
Z operación anterior
LOAD sA, 7B
LOAD sB, A2 [sC,sB, sA] = 14 A2 7B Los valores son iguales Z=1, C=0.
LOAD sC, 14
COMPARE sA, 7B 14A27B - 14A27B = 000000
COMPARACIÓN sB, A2
COMPARACIÓN
Página
sC, 14
Copyright 2010-2014 Xilinx
JUMP Z, igual
[sB, sA] = A2 7B LOAD sA, 7B
LOAD sB, A2
A27B - B97B = (-) E900 COMPARE sA, 7B
COMPARACIÓN sB, B9
[sB, sA] < B97BZ=0 , JUMP C, menor_que
C=1.

Página Copyright 2010-2014 Xilinx


SL 0 SL 1 SLX sX SLA sX
sX sX
Todas estas instrucciones desplazan el contenido del registro especificado (sX) un bit a la izquierda. El bit más significativo (MSB) se desplaza fuera del
registro al indicador de acarreo (C). El bit que se desplaza al bit menos significativo (LSB) viene definido por la instrucción de desplazamiento a la
izquierda utilizada. La bandera cero (Z) se activará sólo si los 8 bits del valor resultante contenido en el registro son cero.

sX
SL 0 sX C '0' Z =? SL0 sX desplaza un '0' al LSB. La bandera Z sólo se activará si bits(7:1)
también son todos '0' después del desplazamiento.
sX
SL 1 sX C '1' Z =0 SL1 sX desplaza un '1' al LSB. Esto significa que la bandera Z
se borrará siempre (Z=0) con esta instrucción.
sX
SLX sX C Z =? SLX sX replica el estado existente del LSB. La bandera Z sólo se
activará si los 8 bits del registro son cero.
sX
SLA sX C C Z =? SLA sX desplaza el estado previo de la bandera de acarreo al
Anterior LSB al mismo tiempo que la bandera de acarreo se carga con el
MSB. La bandera Z sólo se activará si los 8 bits del registro son
cero.

Ejemplos

Un desplazamiento a la izquierda inyectando un '0' tiene el efecto de multiplicar un valor por 2. La instrucción 'SLA' permite desplazar valores multibyte
contenidos en varios registros.
LOAD sB, 14 SLA s B SL 0 sA
LOAD sA, B5 [sB,sA] = 14B5 = 530110 = 0001 0100 1011 0101 sB sA
SL0 sA C C '0'
SLA sB
[sB,sA] = 296A = 1060210 = 0010 1001 0110 1010
y
LOAD sF, 00000001'b e
bucle: SALIDA sF, Da salida a un patrón simple que se muestra a la derecha en el l
puerto SLX sF puerto "to". El proceso termina cuando se han establecido los 8 bits d
Página
JUMP NC, bucle Copyright 2010-2014 Xilinx
esplazamiento final establece la bandera de acarreo. 00000001
00000011
00000111
00001111
00011111
00111111
01111111
11111111

Página Copyright 2010-2014 Xilinx


SR0 sX SR1 sX SRX sX SRA sX
Todas estas instrucciones desplazan el contenido del registro especificado (sX) un bit a la derecha. El bit menos significativo (LSB) se desplaza del registro
al indicador de acarreo (C). El bit que se desplaza al bit más significativo (MSB) viene definido por la instrucción de desplazamiento a la derecha utilizada.
El indicador de cero (Z) se activará sólo si los 8 bits del valor resultante contenido en el registro son cero.

sX
SR0 sX '0' C Z =? SR0 sX desplaza un '0' al MSB. La bandera Z sólo se activará si
bits(6:0) también son todos '0' después del desplazamiento.
sX
SR1 sX '1' C Z =0 SR1 sX desplaza un '1' al MSB. Esto significa que la bandera Z
siempre se borrará (Z=0) con esta instrucción.
sX
SRX sX C Z =? SRX sX replica el estado existente del MSB. La bandera Z sólo se
activará si los 8 bits del registro son cero.
sX
SRA sX C C Z =? SRA sX desplaza el estado anterior de la bandera de acarreo al
Anterior MSB al mismo tiempo que la bandera de acarreo se carga con el
LSB. La bandera Z sólo se activará si los 8 bits del registro son
Ejemplos cero.

Un desplazamiento a la derecha tiene el efecto de dividir un valor por 2. La instrucción "SRA" permite desplazar valores multibyte contenidos en
varios registros. Cuando se utiliza el complemento a 2 para representar valores con signo, "SRX" implementa la extensión de signo.
LOAD sB, ED SRX s SRA sA
LOAD sA, 2A [sB,sA] = ED2A = -482210 = 1110 1101 0010 1010 B sA
SL0 sA sB C C
SLA sB
[sB,sA] = F695 = -241110 = 1111 0110 1001 0101
10000000
01000000
LOAD sF, 10000000'b 00100000
bucle: SALIDA sF, Salidas a 'puerto' un patrón simple 'caminar 1' como se ilustra en el lado
puerto SR0 sF
derecho.
JUMP NC, bucle
00000001
00000000
Página Copyright 2010-2014 Xilinx
00010000
proceso termina cuando el '1' se desplaza a la bandera de acarreo.
00001000
00000100
00000010

00000001
00000000
Página Copyright 2010-2014 Xilinx
RL sX
RR sX
Las instrucciones "RL" y "RR" desplazan el contenido del registro especificado (sX) un bit a la izquierda o a la derecha. El bit que se desplaza de un extremo
del registro al otro también se copia en la bandera de acarreo (C). El indicador de cero (Z) se activará sólo si los 8 bits del contenido del registro son cero.

sX RL sX desplaza todos los bits un lugar a la izquierda y el MSB que se


RL sX C
desplaza
Z =? out se desplaza al LSB y se copia en la bandera de acarreo. La
bandera Z sólo se activará si todos los bits del registro son cero.

RR sX desplaza todos los bits un lugar a la derecha y el LSB que se


RR sX sX
desplaza
C Z =? out se desplaza al MSB y se copia en la bandera de acarreo. La
bandera Z sólo se activará si todos los bits del registro son cero.

Tenga en cuenta que como las instrucciones de rotación sólo reorganizan el contenido existente de 'sX', la bandera cero sólo se activará si 'sX' contenía
cero al entrar en la operación de rotación.

Ejemplo

Las operaciones de rotación se utilizan normalmente en la generación de patrones o secuencias de bits, como en el control
de motores paso a paso.

CARGAR s6, 03
bucle: OUTPUT s6, En este ejemplo podemos imaginar un motor paso a paso que tiene 8
motor_ctrl CALL bobinas dispuestas en un círculo de tal manera que la bobina asignada
step_delay INPUT s0, al bit0 es adyacente a la bobina asignada al bit7. La posición del motor
direction TEST s0, está definida por las bobinas que están siendo energizadas y en este
01 caso es beneficioso energizar dos bobinas adyacentes de un motor al
JUMP NZ, move_right mismo tiempo (de ahí el valor inicial de 03 cargado en 's6').
RL s6
JUMP bucle
Página
mover_derecha: RR s6 Copyright 2010-2014 Xilinx
determinar en qué dirección debe girar el motor y esto se traduce en la
dirección en la que gira el patrón "11", ya sea hacia la izquierda o hacia
la derecha.
00000011
00000110
00001100
00011000
00110000 Izquierda
01100000
11000000
10000001
00000011
00000110
00000011
10000001 Derecha
11000000
01100000

Página Copyright 2010-2014 Xilinx


REGBANK A
REGBANK B
El KCPSM6 tiene 32 registros que están organizados en 2 bancos de 16 Banco por defecto
registros llamados banco 'A' y banco 'B'. Sólo un banco puede estar activo en
un momento dado y todas las instrucciones (excepto "STAR") sólo pueden
realizar operaciones con los registros del banco activo. En otras palabras, los
registros del banco inactivo están casi completamente aislados y su contenido BANCO BANCO
no se ve afectado por las instrucciones que modifican los valores de los A B
registros del banco activo. sF sF

Después de la configuración del dispositivo, o de un pulso de reset Alto activo sE sE


en la entrada 'reset' de la macro KCPSM6, el banco 'A' será el banco activo.
Por lo tanto, se puede considerar que el KCPSM6 tiene inicialmente 16 sD sD
registros y esto será adecuado para muchas aplicaciones.
sC sC

La instrucción REGBANK puede utilizarse para seleccionar qué banco debe sB sB


estar activo y, por lo tanto, asignar el otro banco a inactivo. Sólo hay una
bandera de acarreo y una bandera de cero, ninguna de las cuales se ve sA sA
afectada por la selección de banco.
s9 s9
REGBANK A - Seleccione el banco A activo (o restaure el banco por defecto). s8 s8

s7 s7
REGBANK B - Selecciona el banco B activo.
s6 s6

Sugerencia - Cuando se selecciona un banco diferente no hay ningún efecto s5 s5


sobre el contenido de ninguno de los registros de ambos bancos. Sin
embargo, es casi seguro que aparecerá como si el contenido de todos los s4 s4
registros cambiara a medida que se realiza el intercambio. Tenga en cuenta
que sólo hay un conjunto de banderas y sus valores no cambiarán. s3 s3

s2 s2
Sugerencia - Si utiliza la directiva NAMEREG en su código, probablemente
querrá asignar nombres diferentes a los registros que siguen a la instrucción s1 s1
REGBANK para reflejar que ya no está accediendo a la misma información.
s0 s0

Página Copyright 2010-2014 Xilinx


Aparte de que el banco "A" es el predeterminado en el encendido o después de un reinicio, usted es completamente libre de seleccionar el banco "A" o el
banco "B" como y cuando lo desee utilizando una instrucción REGBANK. Todas las instrucciones sólo operan en los registros del banco seleccionado
activamente, lo que preserva los valores del banco inactivo. Esto puede ser particularmente útil cuando se crea una subrutina que implementa una tarea
intensa; tener muchos registros disponibles para manipular datos puede hacer que la tarea sea mucho más fácil de implementar. También es muy atractivo
cuando se atiende una interrupción, ya que el intercambio de bancos puede ayudar a asegurar que no se perturbe el contenido de los registros que se están
utilizando en cualquier otra parte del programa en el momento de la interrupción. Esto se trata con más detalle en la sección de interrupciones de esta guía
(ver página 86 ).

El KCPSM3 sólo tenía un banco de registros, por lo que una técnica habitual consistía en conservar el contenido de los registros en la memoria scratch pad
antes de volver a utilizar dichos registros en una subrutina. Los valores eran entonces recuperados de la memoria para restaurar sus valores antes de
volver al programa principal. Ésta sigue siendo una técnica perfectamente válida en los programas KCPSM6, pero puede dar lugar a un número significativo
de instrucciones STORE y FETCH que consumen espacio de código y ralentizan la ejecución del programa. Cambiando al banco 'B' de registros al inicio de
una subrutina intensa, o al atender una interrupción, puedes proveerte de 16 registros temporales en un ciclo de instrucción (2 ciclos de reloj del sistema)
preservando automáticamente el contenido de los registros del banco 'A'.

Aunque es útil tener dos bancos de registros aislados e independientes, esto Banco Activo Banco inactivo
también presenta un reto cuando se trata de pasar datos entre un programa
principal y una subrutina. Una vez más, una posible solución es asignar
posiciones de memoria particulares al bloc de notas a las que accedan ambas
secciones de código cuando utilicen bancos de registros diferentes, pero esto
sF sF
requiere una posición de memoria y un par de instrucciones STORE y FETCH
para cada byte de datos. Por esta razón, la instrucción 'Send To Alternate sE sE
Register' ('STAR') le proporciona una forma de pasar información desde un
registro del banco activo (sY) a un registro del banco inactivo (sX) o de sD sD
preestablecer una constante en un registro del banco inactivo.
Sugerencia - Al igual que las instrucciones "LOAD", las instrucciones "STAR" no
afectan a los estados de las banderas. Sin embargo, debe reconocerse que s2 s2 0 0 1 1 0 1 1 1
'STAR s0, s0' no es equivalente a una instrucción 'no-operación' porque cada
referencia a 's0' está en un banco diferente (es decir, 's0' en el banco inactivo s1 s1
probablemente cambiará).
s0 s0
Ejemplo (Efecto ilustrado en el diagrama)
's1' en el
STAR sE, s1 sE' en el banco inactivo se carga con una copia de 's1' en el banco activo.
STAR s1, 37 banco
Página Copyright 2010-2014 Xilinx
inactivo se carga con el valor constante 37 hex (observe que 's1' en el banco activo no cambia). C Sin cambios

STAR sX , kk
REQUISITOS DE CODIFICACIÓN DEL
Z Sin cambios

El registro alternativo 'sX' debe especificarse utilizando un nombre por defecto 's0' a 'sF'. Las directivas
NAMEREG no se aplican a la especificación de "sX". El registro activo actual "sY" debe especificarse utilizando un

STAR sX , sY
ENSAMBLADOR
al utilizar la instrucción STAR
nombre activo para un registro (es decir, NAMEREG se aplica normalmente). Se trata de reglas de codificación
deliberadas que pretenden minimizar el
probabilidad de errores de codificación (es decir, obligan a pensar detenidamente qué banco está activo).

Página Copyright 2010-2014 Xilinx


Puertos de
entrada

A = PUERTO kcpsm6 tu_programa


00 [17:0]
B = PUERTO instrucción bram_enable activa instrucción
01 direcció [11:0]
r
C = PUERTO rdl
02 n direcci
D = PUERTO
03 ón

[7:0]
D 11 clk
[7:0]
C 10 [7:0] [7:0]
puerto_ out_port Puertos de
[7:0]
de_entr
B 01
write_strobe salida
ada
[7:0]
A 00
read_strobe [3] CE
[1] k_write_strobe [7:0]
D Z
[0] [7:0] = PUERTO 08
port_id
CE
[2] [7:0]
D Y
interrupt interrupt_ack
= PUERTO 04
sleep

reset CE
[1] [7:0]
D X
clk
= PUERTO 02

Página Copyright 2010-2014 Xilinx


CE
Este diseño se ha utilizado [0]
para evaluar las velocidades [7:0]
de reloj
Este diagrama representa una posible disposición en la que el KCPSM6 puede utilizarse
máximaspara
quedar servicio D W
a 4 puertos de entrada y 4 puertos de salida de propósito general. Cada puerto es para
de hasta 8 bits y podría
distintos tipos de dispositivos
| (-2)y grados de velocidad...
~105MHz| (-3)

Puertos de E/S de propósito general


conectarse directamente a los pines en el paquete del dispositivo o puede conectarseSpartan-6:
a alguna de su ~82MHz
otra = PUERTO 01
(-1L) ~136MHz
lógica dentro del dispositivo. Todos los diseños KCPSM6 se basan en Virtex-6: (-1) ~185MHz || (-3) ~238MHz
Kintex-7:
variaciones de esta disposición fundamental. En la página 51 se muestra el código PSM adecuado para
Virtex-7: || (-3) ~238MHz
este circuito. || (-3) ~232MHz

Página Copyright 2010-2014 Xilinx


INPUT sX, pp
INPUT sX, (sY)
Una instrucción 'INPUT' permite al KCPSM6 leer información del de tu diseño hardware en un registro 'sX' utilizando un puerto de entrada de propósito
general especificado por un valor constante de 8 bits 'pp' o el contenido de otro registro '(sY)'. KCPSM6 presenta la dirección de puerto definida por 'pp' o
'(sY)' en 'port_id' y su interfaz hardware es entonces responsable de seleccionar y presentar la información apropiada al 'in_port' para que pueda ser
capturada en el registro 'sX'. También se genera un pulso síncrono activo alto ('1') en el pin 'read_strobe' y puede ser utilizado por la interfaz de hardware
para confirmar cuándo se ha leído un puerto en particular.
ENTRADA sX, pp
clk
ENTRADA sX, (s Y)
kcpsm6
dirección
[7:0] sX
puerto_ ENTRADA sX, pp
de_entr instrucción
C Sin cambios
ada
Z Sin read_strobe read_strobe
cambios
s Y o pp [7:0]
clk port_id port_id pp

puerto_de_entrada

Sugerencia 1 - Asigne las direcciones de los puertos de entrada de forma que el multiplexor de
selección de datos que alimenta 'in_port' utilice el número mínimo de señales 'port_id' para realizar Hay 2 ciclos de reloj disponibles
la selección, por ejemplo, las direcciones de puerto '00' a '0F' proporcionan 16 puertos de entrada y para descodificar la dirección de
sólo requieren que 'port_id(3:0)' sean entradas de selección para el multiplexor, lo que resulta en puerto 'pp' o '(sY)' y presentar la
diseños más pequeños y rápidos. información solicitada al 'in_port'.

Pista 2 - A menos que haya una razón específica para no hacerlo, el multiplexor de selección de datos Datos capturados en 'sX' en
de entrada debe incluir un registro pipeline (es decir, su declaración case debe estar dentro de un este flanco de reloj
proceso con reloj). De esta forma, los datos se seleccionan durante el primer ciclo de reloj de 'port_id' y ascendente.
se presentan a 'in_port' durante el segundo ciclo de reloj. No definir un registro de canalización en
cualquier punto de la ruta de 'port_id' a 'in_port' es la razón más común por la que los diseños
PicoBlaze no alcanzan el rendimiento requerido (una 'ruta falsa' durante un ciclo de reloj) .

Pista 3 - 'read_strobe' puede ignorarse en la mayoría de los casos y nunca necesita formar parte del multiplexor que alimenta 'in_port'. Sin embargo, algunas
Página Copyright 2010-2014 Xilinx
funciones como un búfer FIFO necesitan saber cuándo han sido leídas y es en esas situaciones en las que 'read_strobe' junto con una decodificación del valor
apropiado de 'port_id' se utilizaría para generar un pulso "el puerto ha sido leído" para confirmar cuándo ha tenido lugar una lectura.

Página Copyright 2010-2014 Xilinx


OUTPUT sX, pp
OUTPUT sX, (sY)
An ‘OUTPUT’ instruction is used to transfer information from a register ‘sX’ to a general purpose output port specified by an 8-bit constant value ‘pp’ or the
contents of another register ‘(sY)’. KCPSM6 presents the contents of the register ‘sX’ on ‘out_port’ and the port address defined by ‘pp’ or ‘(sY)’ is presented
on ‘port_id’. Both pieces of information are qualified by an active High (‘1’)
pulso síncrono en el pin 'write_strobe'. Su interfaz de hardware es clk
responsable de capturar la información presentada.
OUTPUT sX, pp
instrucción de
OUTPUT sX, (s Y)
kcpsm6 SALIDA sX, pp
sX [7:0]
dirección
puerto_salida sX

puerto_salida
Z Sin cambios C Sin cambios
write_strobe write_strobe pp
s Y o pp
[7:0]
clk port_id port_id Hay 2 ciclos de reloj disponibles para
decodificar la dirección del puerto
'pp' o '(sY)' p solo 3-
Ten en cuenta que 'out_port' y 'port_id' variarán durante la ejecución de otras instrucciones pero u bits de
'write_strobe' sólo estará activo durante una instrucción OUTPUT. e 'port_id'
r junto con
Sugerencia - En la mayoría de los casos se utiliza una dirección de puerto fija 'pp' por lo que las t 'write_str
directivas CONSTANT proporcionan un ideal por qué realizar un seguimiento de sus o obe' son
asignaciones de puerto y hacer su código más fácil de escribir, entender y mantener. decodific
0 ados.
Ejemplos 5
Si quieres que tus diseños sean pequeños y rápidos, asigna Se pueden
CONSTANTE LED_puerto, h utilizar valores
05 direcciones de puerto que faciliten funciones lógicas más
pequeñas. e decimales para
; x especificar las
CARGA s3, 3A
direcciones de
SALIDA s3, puerto_lED En este ejemplo un conjunto de 8 LEDs son mapeados al y
Página Copyright 2010-2014 Xilinx
los puertos, pero normalmente es más fácil trabajar con valores
hexadecimales o binarios a la hora de definir el hardware.

El valor presentado en 'out_port' debe


ser capturado en el flanco ascendente
del reloj cuando 'write_strobe' es Alto.
VHDL
if clk'event and clk = '1' then
if write_strobe = '1' then
if port_id(2 downto 0) = "101" then
led <=
puerto_salida; end
if;
end if;
end if;

Página Copyright 2010-2014 Xilinx


Constante -Puertos de salida optimizados
Para entender el motivo de los puertos optimizados para constantes y saber cuándo es mejor utilizarlos, es necesario apreciar las situaciones en las que los
puertos de salida generales pueden afectar negativamente al tamaño del código de tu programa y/o resultar en un menor rendimiento. Las instrucciones
'OUTPUT sX, pp' y 'OUTPUT sX, (sY)' asociadas a los puertos de salida de propósito general requieren que el valor a escribir en el puerto se mantenga en
un registro 'sX'. Esto es ideal cuando el valor es una variable en tu sistema pero cuando quieres enviar un valor constante, o más probablemente, una serie
de valores constantes a un puerto el acto de cargar 'sX' cada vez incrementa el tamaño del código y reduce el rendimiento. En muchas aplicaciones esta
sobrecarga puede ser tolerada y no deberías sentirte presionado para adaptar tu diseño y código para usar los puertos optimizados para constantes a
menos que realmente quieras hacerlo. Sin embargo, el uso apropiado de los puertos optimizados de forma constante puede hacer que el código sea más
fácil de escribir y evitar el tamaño del código y la sobrecarga de rendimiento asociada a los puertos de salida de propósito general cuando sea necesario.

En este ejemplo se requiere que el KCPSM6 escriba datos de 8 bits a un dispositivo externo. Los datos
Utilización de puertos de salida de
son naturalmente variables y se presentan a la interfaz del dispositivo mediante la salida al puerto 20
propósito general......
hex. Entonces se requiere que el KCPSM6 genere la secuencia correcta de señales de control;
'Dev_write' se pone a Alto antes de que se genere un pulso en el 'Dev_clk' seguido de que 'Dev_write' se
devuelva a Bajo. Estas señales se controlan mediante la salida de la secuencia apropiada de valores
kcpsm6
constantes al puerto 08 hex que definen los estados de bit0 y bit1.
[7:0] (Esta técnica de conducción de señales de control suele denominarse
puerto_sali
"golpeteo de bits").
da PUERTO 20
CE
write_strobe [7:0]
[5] D
Dev_data[7:0] Datos válidos
[1]
08
PUERTO [0]
Dev_write
CE
[7:0] Dev_clk
[3] D
[7:0]
clk port_id OUTPUT s1,
Puerto_datos_dispositivo
Para cada instrucción OUTPUT de LOAD s0, 00000010'b
la forma de onda de la secuencia OUTPUT s0, Dev_control_port
CONSTANT Puerto_datos_dev, 20 de control hay una instrucción LOAD s0, 00000011'b
CONSTANT Puerto_de_control_dev, LOAD correspondiente que OUTPUT s0, Dev_control_port
08 prepara 's0' con el valor constante LOAD s0, 00000010'b
OUTPUT s0, Dev_control_port
Página Copyright 2010-2014 Xilinx LOAD s0, 00
r
e
q
u
e
r
i
d
o
.

Página Copyright 2010-2014 Xilinx


Constante -Puertos de salida optimizados
El diagrama de temporización para el código que utiliza los puertos de salida de propósito general muestra que se necesitan 16 ciclos de reloj del sistema
para generar la secuencia de control porque cada instrucción necesita 2 ciclos de reloj y cada instrucción OUTPUT requiere la correspondiente instrucción
LOAD para inicializar 'sX' (en el ejemplo se ha utilizado 's0'). También se puede ver que esto resulta en 4 ciclos de reloj entre cada transición de la
secuencia de control.

clk

instruction SALIDA CARG SALIDA CARG SALIDA CARG SALIDA CARG SALIDA
AR AR AR AR
puerto_salida datos 02 03 02 00

write_strobe
Dev_data[7:0] Datos
válidos
Dev_write

Dev_clk

16 ciclos de
reloj

Hay una serie de aplicaciones en las que es beneficioso que el KPCSM6 ralentice la generación de formas de onda. Por ejemplo, la velocidad de
comunicación con un dispositivo de memoria SPI Flash puede ser de 33MHz como máximo. Por lo tanto, si el reloj del sistema es de 200 MHz, habría que
dividirlo al menos por un factor de 6 y KCPSM6 podría ayudar a conseguirlo de forma natural. Sin embargo, si necesitas un mayor rendimiento de "golpeo
de bits" sin simplemente aumentar la frecuencia del reloj del sistema, entonces claramente hay un límite cuando se utilizan los puertos de salida de
propósito general.

Una posible solución que se ha utilizado en diseños basados en KCPSM3 en el pasado, y que sigue
OUTPUT s1, Dev_data_port
siendo aplicable a los diseños KCPSM6, es reordenar el código. Como se muestra a la izquierda, los
LOAD s2, 00000010'b
valores constantes se han precargado en un conjunto de registros para que la forma de onda pueda
LOAD s3, 00000011'b
generarse con una ráfaga de instrucciones OUTPUT secuenciales. Aunque esto da como resultado la
LOAD s0, 00000000'b
mayor velocidad de transición posible de las señales durante la generación de la secuencia, también
OUTPUT s2, Dev_control_port
requiere el uso de más registros y la misma cantidad de tiempo para ejecutar el código.
OUTPUT s3, Dev_control_port
OUTPUT s2, Dev_control_port
Sugerencia - Para generar pulsos de un solo ciclo de reloj puede utilizar el ciclo de reloj único 'write_strobe'
OUTPUT s0, Dev_control_port
Página Copyright 2010-2014 Xilinx
calificado por
el 'port_id' en lugar de establecer y restablecer un bit de datos de un puerto de salida completo.

Página Copyright 2010-2014 Xilinx


Constante -Puertos de salida optimizados
El KCPSM6 proporciona hasta 16 puertos de salida optimizados para constantes. Desde el punto de vista del hardware, estos puertos se utilizan de forma
idéntica a los puertos de salida de propósito general, excepto que "k_write_strobe" se utiliza para calificar la dirección del puerto que se presenta en
port_id[3:0]. Por lo tanto, sólo pueden utilizarse las direcciones de puerto '0' a 'F' (0'd a 15'd) y port_id[7:4] debe ignorarse. Los diseños óptimos asignarán
las direcciones de los puertos de salida para minimizar la decodificación de 'port_id', por lo que esto no debería plantear ningún problema.

Volviendo al mismo ejemplo de escritura de datos a un dispositivo externo podemos ver que el puerto 08 hex ahora ha sido asignado a un puerto de salida
optimizado para constante mediante el uso de 'k_write_strobe' mientras que el puerto 20 hex sigue asociado a 'write_strobe' porque los datos son
naturalmente variables. Así que hay muy poca diferencia en el hardware siempre y cuando recuerdes que sólo port_id[3:0] se define durante una
instrucción OUTPUTK. Ten en cuenta también que ahora podrías tener dos puertos de salida diferentes con la misma dirección; uno para datos variables
y otro para valores constantes (ver página 79).

Utilización de un puerto de salida con optimización constante y un puerto de salida de propósito general......
kcpsm6
[7:0]
puerto_sali PUERTO 20
da
CE
write_strobe [5]
[7:0]
D Dev_data[7:0] Datos válidos

[1]
PUERTO 08 Dev_write
[0]
k_write_strobe CE Dev_clk
[3] [7:0]
[7:0] D
clk port_id

Se puede ver inmediatamente


que todas las instrucciones
CONSTANT Puerto_datos_dev, 20 LOAD han sido eliminadas
CONSTANT Puerto_de_control_dev, ahorrando espacio de código y
08 reduciendo el tiempo de
ejecución. Esto también significa
que el registro 's0' utilizado

Página Copyright 2010-2014 Xilinx


ente para definir la secuencia de Código más pequeño y rápido
valores está ahora libre para otro
propósito. OUTPUT s1, Puerto_datos_dispositivo
OUTPUTK 00000010'b, Dev_control_port
OUTPUTK 00000011'b, Dev_control_port
OUTPUTK 00000010'b, Dev_control_port
OUTPUTK 00000000'b, Dev_control_port

Página Copyright 2010-2014 Xilinx


Puertos de salida con
optimización constante OUTPUTK
Código más pequeño y rápido
kk, p
instrucción clk
SALIDAK SALIDAK SALIDAK SALIDAK OUTPUT s1, Puerto_datos_dispositivo
OUTPUTK 00000010'b, Dev_control_port
SALIDA
02 03 02 00 OUTPUTK 00000011'b, Dev_control_port
puerto_salida OUTPUTK 00000010'b, Dev_control_port
d a t o s OUTPUTK 00000000'b, Dev_control_port
write_strobe Sugerencia - El uso de una directiva TABLE
Válid Datos
Dev_datos[7:0] también facilitaría la escritura de este
o
código.
k_write_strobe Este diagrama de temporización muestra claramente
Dev_write la ventaja de rendimiento cuando se utiliza un puerto
de salida optimizado constante para una aplicación
Dev_clk de "golpeo de bits". La secuencia de control de
ejemplo se completa ahora en 8 en lugar de
8 ciclos de 16 ciclos de reloj. Y lo que es más significativo, la
velocidad de transición estándar es cada instrucción o
reloj cada 2 ciclos de reloj del sistema. Todo ello sin
SALIDAK kk, p necesidad de utilizar ningún registro.

La instrucción OUTPUTK tiene dos operandos. El primer operando es el valor constante de 8 bits "kk" que se presentará en "puerto_salida" y, por lo tanto,
debe estar comprendido entre "00" y "FF" hexadecimal. El segundo operando debe especificar la dirección del puerto que se presentará en port_id[3:0] y
por lo tanto debe estar en el rango de '0' a 'F' hex. Esta instrucción no afecta al contenido de los registros utilizados ni al estado de las banderas.

Ejemplos
Estos ejemplos muestran cómo el ensamblador KCPSM6 permite definir y especificar la constante y el
CONSTANT token, 61 puerto de múltiples maneras. ¡Las cuatro instrucciones 'OUTPUTK' mostradas son en realidad la misma!
CONSTANT control_port, 0A
El valor de la constante 'kk' puede especificarse inmediatamente utilizando hexadecimal, decimal o un
OUTPUTK 61, A carácter ASCII. Alternativamente se puede utilizar el nombre asignado a una constante por una directiva
OUTPUTK 97'd, 10'd CONSTANT.
OUTPUTK "a", A
OUTPUTK token, puerto_de_control La dirección de puerto 'p' también puede especificarse inmediatamente usando hexadecimal o decimal,

Página Copyright 2010-2014 Xilinx


pero recuerde que sólo puede estar en el rango de '0' a 'F' (0'd a 15'd). Del mismo modo, se puede
utilizar el nombre de la constante definida por una directiva CONSTANT siempre que el valor que se le
asigne también esté dentro del rango requerido.

Página Copyright 2010-2014 Xilinx


Implementación de puertos de salida híbridos
Siempre que sea necesario enviar datos variables a un puerto de salida, debe utilizarse un puerto de salida de propósito general. Sin embargo,
principalmente para mejorar la densidad del código, la instrucción 'OUTPUTK kk, p' es más adecuada en algunas situaciones, por lo que resulta deseable
enviar constantes al mismo puerto. Esto se puede conseguir simplemente asignando la misma dirección de puerto (en el rango de '00' a '0F' hex) para ser
utilizada por las instrucciones 'OUTPUT sX, pp' y 'OUTPUTK kk, p' e implementando un puerto híbrido en hardware.

A continuación se muestra un ejemplo de puerto híbrido. En este caso se requiere que el KCPSM6 envíe información a un transmisor UART para ser
observada en una terminal PC. Como es lógico, la información será una serie de caracteres ASCII, pero muchos de ellos serán cadenas o constantes
predefinidas, mientras que otros representarán los datos variables que se mostrarán. Este ejemplo también ilustra un posible uso del control 'sleep' y la
directiva 'STRING' en el ensamblador KCPSM6.

[7:0]
puerto_sa datos_e salida_ser
hwbuild => X "41", lida n ie

write_strobe escribir_a_ua
[3] rt escribir_buffer
k_write_strobe
[7:0]
buffer_half_full
port_id
dormir PUERTO clk
08
clk

kcpsm6uart_tx (incluye búfer FIFO de 16 bytes)

Descodificación de puertos híbridoswrite_to_uart


en VHDL <= (k_write_strobe o write_strobe) y port_id(3);

Para crear un puerto híbrido la dirección del puerto debe estar en el rango de '00' a '0F' hex y en este ejemplo se ha utilizado 08 hex en una decodificación
optimizada de 'port_id' (es decir, sólo se está observando realmente port_id[3] para minimizar la función lógica que realiza la decodificación). A continuación,
tanto "write_strobe" como "k_write_strobe" se utilizan para calificar la dirección del puerto de modo que una instrucción "OUTPUT sX, 08" o "OUTPUT kk, 8"
dará lugar a la escritura de datos en el búfer FIFO dentro de la macro del transmisor UART.

Página Copyright 2010-2014 Xilinx


El diagrama del circuito también muestra cómo la salida de estado "medio lleno" del búfer FIFO podría utilizarse para hacer que el KCPSM6 espere (duerma)
cada vez que el búfer comience a
y esta forma hardware de handshaking es importante si se quiere conseguir densidad de código como veremos en la página siguiente....

Página Copyright 2010-2014 Xilinx


Implementación de puertos de salida híbridos y cadenas
de texto
Archivo
PSM
Este código utiliza el puerto híbrido para mostrar el estado de construcción del hardware en la pantalla
CONSTANTE Puerto_Tx_UART, 08
del terminal del PC.
;
STRING hw_intro$, "Hardware Build: "
OUTPUTK hw_intro$, UART_Tx_port Construcción de
HWBUILD s0 hardware: A
El código explota la directiva STRING para describir la secuencia de 16 valores constantes
OUTPUT s0, puerto UART_Tx
requeridos para enviar 'Hardware Build: ' a la UART utilizando instrucciones 'OUTPUTK'. A
OUTPUTK 0D, puerto UART_Tx
continuación carga 's0' con el valor 'hwbuild' definido como 41 hex (carácter "A") utilizando el
genérico KCPSM6 (ver páginas 34 y 100) que envía a la UART utilizando una instrucción
'OUTPUT'. La comunicación se completa enviando un retorno de carro (0D hex) mediante una
instrucción 'OUTPUTK'.
KCPSM6
El archivo LOG muestra cómo se ha utilizado la cadena de texto para
Archivo
expandir el código en múltiples instrucciones 'OUTPUTK'. En
LOG
condiciones normales de funcionamiento, la secuencia completa de 19
instrucciones se ejecutará en sólo 38 ciclos de reloj del sistema. Por lo
000 2B488 OUTPUTK 48[hw_intro$: "H"], 8[UART_Tx_port]
tanto, es vital que aquello a lo que envíes datos tenga la capacidad de
001 2B618 OUTPUTK 61[hw_intro$: "a"],
recibir información a esa velocidad. En este ejemplo, el transmisor
002 2B728 8[UART_Tx_port] OUTPUTK 72[hw_intro$:
UART sólo tiene un búfer FIFO de 16 caracteres, por lo que la solución
003 2B648 "r"], 8[UART_Tx_port] OUTPUTK
es el handshaking por hardware aprovechando el control "sleep". Una
004 2B778 64[hw_intro$: "d"], 8[UART_Tx_port]
alternativa sería tener un búfer FIFO más grande y asegurarse de que
005 2B618 OUTPUTK 77[hw_intro$:"w"], 8[UART_Tx_port]
tiene suficiente espacio libre antes de empezar a enviar los caracteres
006 2B728 OUTPUTK 61[hw_intro$: "a"],
(es decir, comprobar si el FIFO está vacío antes de enviar la ráfaga de
007 2B658 8[UART_Tx_port] OUTPUTK 72[hw_intro$: CALL test_FIFO_full
información).
008 2B208 "r"], 8[UART_Tx_port] OUTPUTK OUTPUTK "H", 8
009 2B428 65[hw_intro$: "e"], 8[UART_Tx_port] Tenga en cuenta que si tuviera que CALL test_FIFO_full
00A 2B758 OUTPUTK 20[hw_intro$:" "], 8[UART_Tx_port] implementar una comprobación basada OUTPUTK "a", 8
00B 2B698 OUTPUTK 42[hw_intro$: "B"], en software del estado del FIFO
00C 2B6C8 8[UART_Tx_port] OUTPUTK 75[hw_intro$: mediante la lectura de un puerto de
00D 2B648 "u"], 8[UART_Tx_port] OUTPUTK entrada, entonces aumentaría el código
00E 2B3A8 69[hw_intro$: "i"], 8[UART_Tx_port] al mismo tamaño que tendría si sólo
00F 2B208 OUTPUTK 6C[hw_intro$:"l"], 8[UART_Tx_port] utilizara un puerto de salida de LOAD s1, "H"
010 14080 OUTPUTK 64[hw_intro$: "d"], 8[UART_Tx_port] propósito general . Por lo tanto, los CALL send_to_UART
011 2D008 OUTPUTK 3A[hw_intro$:":"], 8[UART_Tx_port] esquemas de handshaking hardware LOAD s1, "a"
012 2B0D8 OUTPUTK 20[hw_intro$:" "], 8[UART_Tx_port] CALL send_to_UART
Página HWBUILD s0 Copyright 2010-2014 Xilinx
q a clave para ralentizar las secuencias
u 'OUTPUTK' si la densidad del código es
e el objetivo clave.

u Sugerencia - Mira también el soporte de cadenas usando


t 'LOAD&RETURN' (página 99) y la directiva TABLE (página
i 100).
l Sugerencia - Mire también 'all_kcpsm6_syntax.psm'.
i
z
a
n

'
s
l
e
e
p
'

i
n
t
e
r
r
u
p
c
i
o
n
e
s

s
o
n

l
Página Copyright 2010-2014 Xilinx

También podría gustarte