Окончание. Начало в № 12'2007
Валерий ЗОТОВ
Структура микропрограммного обеспечения измерителя частоты цифровых сигналов
В состав микропрограммного обеспечения измерителя частоты цифровых сигналов, предназначенного для реализации на базе инструментального модуля Xilinx Spartan-3E Starter Board, входят:
• основная управляющая программа;
• набор вспомогательных подпрограмм;
• процедура обработки прерывания. Основная управляющая программа выполняет следующие операции:
• инициализация основных функциональных блоков аппаратной части измерителя частоты цифровых сигналов;
• анализ состояния переключателей устройства управления и запись соответствующих значений данных в выходные порты микропроцессорного блока, управляющие работой входных и измерительных узлов;
• вычисление значения частоты входного сигнала на основании данных, записанных в ячейки сверхоперативного запоминающего устройства (СОЗУ);
• вывод результатов измерения частоты на экран жидкокристаллического дисплея. Для выполнения большинства указанных
операций используются соответствующие вспомогательные подпрограммы, обращение к которым производится из основной управляющей программы.
Процедура обработки прерывания предназначена для осуществления следующих операций:
• изменение состояния светодиодных индикаторов;
• чтение информации из 32-разрядных счетчиков измерительных каналов с последующей записью считанных значений в соответствующие ячейки СОЗУ;
• обнуление содержимого счетчиков, входящих в состав измерительного блока.
Измеритель частоты цифровых сигналов, выполненный на основе микропроцессорного ядра семейства PicoBlaze
и реализуемый на базе инструментального комплекта Spartan-3E Starter Kit фирмы Xilinx
В исходном тексте ПО для измерителя частоты цифровых сигналов на языке ассемблера можно выделить следующие модули:
• блок декларации и определения значений констант, используемых в основной управляющей программе и вспомогательных подпрограммах;
• блок инициализации аппаратной части измерительной системы;
• основной модуль управляющей программы;
• подпрограмма вывода вычисленного значения для частоты входного сигнала на жидкокристаллический дисплей;
• подпрограмма преобразования З2-разряд-ного двоичного значения в 40-разрядный (десятизначный) двоично-десятичный код;
• подпрограмма деления З2-разрядного двоичного числа на 10;
• подпрограммы вывода текстовой информации на жидкокристаллический дисплей;
• подпрограммы формирования временных задержек;
• подпрограммы управления работой жидкокристаллического дисплея;
• процедура обслуживания прерывания,
В последующих разделах рассматриваются алгоритмы основной управляющей программы и процедуры обслуживания прерываний и их реализация в виде описаний на языке ассемблера микропроцессорного ядра семейства PicoBlaze,
Алгоритм и исходный текст основной управляющей программы измерителя частоты цифровых сигналов
Алгоритм основной управляющей программы измерителя частоты цифровых сигналов, реализуемого на базе инструментального модуля Xilinx Spartan-3E Starter Board, в наглядном виде представлен на рис, В, Описание данного алгоритма на языке ассемблера микро-
процессорного ядра семейства РкоИаге содержится в первых трех модулях исходного текста микропрограммного обеспечения.
В начале первого модуля исходного текста представлены следующие директивы, предназначенные для определения адресов входных и выходных портов микропроцессорного блока:
;Port definitions
CONSTANT A_count0_port, 00 CONSTANT A_count1_port, 10 CONSTANT A_count2_port, 20 CONSTANT A_count3_port, З0
;32-bit A-counter (LSByte first)
CONSTANT B_count0_port, 40 CONSTANT B_count1_port, 50 CONSTANT B_count2_port, 60 CONSTANT B_count3_port, 70
;32-bit B-counter (LSByte first)
CONSTANT status_port, В0 CONSTANT switch0, 01 CONSTANT switchl, 02 CONSTANT switch2, 04 CONSTANT switch3, 0В CONSTANT AB_switch, 10
4 switches and counter status Switches SW0 — bit0 active High SW1 — bitl SW2 — bit2 SW3 — bit3 0=A-count enabled 1=B-count enabled
CONSTANT count_resetport, 02
CONSTANT a_count_reset, 01 CONSTANT b_count_reset, 02
Reset frequency counter controls A-count = bit0 B-count = bit1
CONSTANT LED_port, 01
; В simple LEDs — active high
CONSTANT source_control_port, 08; Select and control test sources
CONSTANT source_sel0, 01 CONSTANT source_sel1, 02 CONSTANT ring_reset, 40
CONSTANT dcm_kick, 80
LCD interface ports
00 = SMA clock 01=50MHz 10 = DCM Osc 11=Ring Osc active High rest of ring osc — bit6
DCM kick start signal — bit7
;The master enable signal is not used by the LCD display itself ;but may be required to confirm that LCD communication is active. ;This is required on the Spartan-3E Starter Kit if the StrataFLASH ;is used because it shares the same data pins and conflicts must be avoided.
CONSTANT LCD_output_port, 04 ; LCD character module output
; control
CONSTANT LCD_E, 01 CONSTANT LCD_RW, 02 CONSTANT LCD_RS, 04
CONSTANT LCD_drive, 08
; data and
bit0
bit1
; active High Enable E -; Read=1 Write=0 RW —
; Instruction=0
Data=1RS — bit2 ; Master enable (active High) — ; bit3
CONSTANT LCD_DB4, 10 4-bit Data DB4 — bit4
CONSTANT LCD_DB5, 20 interface Data DB5 — bit5
CONSTANT LCD_DB6, 40 Data DB6 — bit6
CONSTANT LCD_DB7, 80 Data DB7 — bit7
CONSTANT LCD_input_port, 09 LCD character module input data
CONSTANT LCD_read_spare0, 01 Spare bits — bit0
CONSTANT LCD_read_spare1, 02 are zero — bit1
CONSTANT LCD_read_spare2, 04 — bit2
CONSTANT LCD_read_spare3, 08 — bit3
CONSTANT LCD_read_DB4, 10 4-bit Data DB4 — bit4
CONSTANT LCD_read_DB5, 20 interface Data DB5 — bit5
CONSTANT LCD_read_DB6, 40 Data DB6 — bit6
CONSTANT LCD_read_DB7, 80 Data DB7 — bit7
В приведенном фрагменте ассемблерного кода микропрограммного обеспечения выполняется декларация и определение значений констант, которые применяются в качестве адресов портов ввода/вывода, предназначенных для чтения содержимого 32-разрядных счетчиков измерительного блока и состояния переключателей управляющего устройства, а также используемых для управления работой селекторов входов, генераторов тестовых сигналов и жидкокристаллического дисплея.
Затем следует группа директив, с помощью которых указываются адреса ячеек сверхоперативного запоминающего устройства, выделяемых для хранения 32-разрядных значений, считываемых из измерительного блока, промежуточных и окончательных результатов вычисления значения для частоты входного сигнала:
;Scratch Pad Memory Locations
CONSTANT count0, 00 ; last 32-bit counter value (LSByte first)
CONSTANT count1, 01 CONSTANT count2, 02 CONSTANT count3, 03
CONSTANT ISR_count, 04 ; count number of interrupts for ; a clean start
CONSTANT decimal0, 11 ; 10 digit decimal value up
; to 4,294,967,295
CONSTANT decimal1, 12 CONSTANT decimal2, 13 CONSTANT decimal3, 14 CONSTANT decimal4, 15 CONSTANT decimal5, 16 CONSTANT decimal6, 17 CONSTANT decimal7, 18 CONSTANT decimal8, 19 CONSTANT decimal9, 1A
CONSTANT preserve_s0, 30 ; place to save register contents
CONSTANT preserve_s1, 31
CONSTANT preserve_s2, 32
CONSTANT preserve_s3, 33
CONSTANT preserve_s4, 34
CONSTANT preserve_s5, 35
CONSTANT preserve_s6, 36
CONSTANT preserve_s7, 37
CONSTANT preserve_s8, 38
CONSTANT preserve_s9, 39
CONSTANT preserve_sA, 3A
CONSTANT preserve_sB, 3B
CONSTANT preserve_sC, 3C
CONSTANT preserve_sD, 3D
CONSTANT preserve_sE, 3E
CONSTANT preserve_sF, 3F
Завершает блок декларации и определения значений констант приведенная ниже последовательность директив, которые устанавливают значение параметра, используемого при формировании программным способом задержки длительностью 1 мкс, и коды символов таблицы Л8СІІ:
;Useful data constants
; For a 50MHz clock the constant value is (10-6)/4 = 11 (0B Hex). CONSTANT delay_1us_constant, 0B ;ASCII table
CONSTANT character_a, 61 CONSTANT character_b, 62 CONSTANT character_c, 63 CONSTANT character_d, 64 CONSTANT character_e, 65 CONSTANT character_f, 66 CONSTANT character_g, 67 CONSTANT character_h, 68 CONSTANT character_i, 69 CONSTANT character_j, 6A CONSTANT character_k, 6B CONSTANT character_l, 6C CONSTANT character_m, 6D CONSTANT character_n, 6E CONSTANT character_o, 6F CONSTANT character_p, 70 CONSTANT character_q, 71 CONSTANT character_r, 72 CONSTANT character_s, 73 CONSTANT character_t, 74 CONSTANT character_u, 75 CONSTANT character_v, 76 CONSTANT character_w, 77 CONSTANT character_x, 78 CONSTANT character_y, 79 CONSTANT character_z, 7A CONSTANT character_A, 41 CONSTANT character_B, 42 CONSTANT character_C, 43 CONSTANT character_D, 44 CONSTANT character_E, 45
CONSTANT character_F, 46 CONSTANT character_G, 47 CONSTANT character_H, 48 CONSTANT character_I, 49 CONSTANT character_J, 4A CONSTANT character_K, 4B CONSTANT character_L, 4C CONSTANT character_M, 4D CONSTANT character_N, 4E CONSTANT character_O, 4F CONSTANT character_P, 50 CONSTANT character_Q, 51 CONSTANT character_R, 52 CONSTANT character_S, 53 CONSTANT character_T, 54 CONSTANT character_U, 55 CONSTANT character_V, 56 CONSTANT character_W, 57 CONSTANT character_X, 58 CONSTANT character_Y, 59 CONSTANT character_Z, 5A CONSTANT character_0, 30 CONSTANT character_1, 31 CONSTANT character_2, 32 CONSTANT character_3, 33 CONSTANT character_4, 34 CONSTANT character_5, 35 CONSTANT character_6, 36 CONSTANT character_7, 37 CONSTANT character_8, 38 CONSTANT character_9, 39 CONSTANT character_colon, 3A CONSTANT character_stop, 2E CONSTANT character_semi_colon, 3B CONSTANT character_minus, 2D CONSTANT character_divide, 2F ;'/' CONSTANT character_plus, 2B CONSTANT character_comma, 2C CONSTANT character_less_than, 3C CONSTANT character_greater_than, 3E
CONSTANT character_equals, 3D CONSTANT character_space, 20 CONSTANT character_CR, 0D ; carriage return
CONSTANT character_question, 3F ; '?'
CONSTANT character_dollar, 24 CONSTANT character_exclaim, 21 ; '!'
CONSTANT character_BS, 08 ; Back Space command
; character
;Initialise the system
cold_start: CALL LCD_reset ;initialise LCD display
LOAD s0, 00 ;Turn off LEDs
OUTPUT s0, LED_port
;Write welcome message to LCD display
LOAD s5, 10 ;Line 1 position 0
CALL LCD_cursor
CALL disp_PicoBlaze ;Display 'PicoBlaze Inside'
CALL delay_1s ;wait 3 seconds
CALL delay_1s
CALL delay_1s
LOAD s5, 10 ;Line 1 position 0
CALL LCD_cursor
CALL disp_Frequency ;Display 'Frequency Counter
;V1.00'
LOAD s5, 21 ;Line 2 position 1
CALL LCD_cursor
CALL disp_Counter
LOAD s5, 2B ;Line 2 position 11
CALL LCD_cursor
CALL disp_version
CALL delay_1s ;wait 5 seconds
CALL delay_1s
CALL delay_1s
CALL delay_1s
CALL delay_1s
CALL LCD_clear ;Clear display
; Kick start the DCM oscillator.
; Just requires a few cyles of activity
LOAD s0, FF
LOAD s1, 00
kick_loop: OUTPUT s1, source_control_port
XOR s1, dcm_kick ;toggle kick start signal
SUB s0, 01
JUMP NZ, kick_loop
; clear all scratch pad memory locations
LOAD s1, 3F
LOAD s0, 00
clear_spm: STORE s0, (s1)
SUB s1, 01
JUMP NC, clear_spm
ENABLE INTERRUPT
Значение параметра delay_1us_constant, определяющего длительность задержки, формируемой программным способом, равно 1 мкс и зависит, прежде всего, от частоты сигнала синхронизации, который используется в качестве тактового для исполнительного модуля КСРЭМ3 микропроцессорного ядра РкоБ1аге. Кроме того, при вычислении этого значения необходимо принимать во внимание время выполнения одной микрокоманды, выраженное в количестве периодов тактового сигнала. С учетом того, что большинство инструкций микропроцессорного ядра семейства РкоБ1аге [2-7] выполняется за два такта, выражение для определения значения параметра задержки delay_1us_constant принимает следующий вид:
delay_1us_constant = (с1оск_тМв- 6)/4, (1)
где clock_тate — значение частоты тактового сигнала исполнительного модуля микропроцессорного ядра РкоБ1аге КСР8М3, выраженное в мегагерцах.
После модуля декларации и определения значений констант следует блок инициализации аппаратной части измерительной системы, который содержит последовательность инструкций, выполняющих начальную установку основных параметров рассматриваемого устройства при включении напряжения питания. В начале этого блока осуществляется вызов подпрограммы инициализации жидкокристаллического дисплея. Далее представлена последовательность микропроцессорных команд, с помощью которых определяются значения начальной позиции курсора и выводятся на ЖК-дисплей сообщения, информирующие о текущей версии программного обеспечения измерителя частоты цифровых сигналов:
Затем следует совокупность инструкций, которая предназначена для активизации генератора тестового сигнала, выполненного на основе цифрового модуля управления синхронизацией ЭСМ. После этих инструкций представлена группа микропроцессорных команд, выполняющих очистку содержимого используемых ячеек СОЗУ. В конце блока инициализации аппаратной части измерительной системы приведена команда установки режима, разрешающего обработку прерываний. Исходный текст рассматриваемого модуля выглядит следующим образом:
Основной модуль управляющей программы представляет собой бесконечный цикл, внутри которого выполняются следующие операции:
• проверка состояния переключателей устройства управления и формирование соответствующей комбинации сигналов выбора для селектора входов;
• вывод на ЖК-дисплей меню выбора входов или условного обозначения выбранного входа;
• считывание информации из ячеек СОЗУ и формирование двоично-десятичного значения частоты входного сигнала;
• отображение текущих результатов измерения частоты входного сигнала на ЖК-дисплее.
Исходный текст основного модуля управляющей программы для измерителя частоты цифровых сигналов имеет следующий вид:
;Main Program
warm_start: LOAD s5, 21 ; Line 2 position 1
CALL LCD_cursor
INPUT sF, status_port ; select source based on switches
COMPARE sF, 00 ; test for no switches active
AND sF, 0F ; isolate switches
JUMP NZ, test_SMA
CALL disp_menu
JUMP warm_start
'PicoBlaze' 'Frequency Counter V1.00'
test_SMA: COMPARE sF, switchO JUMP NZ, test_50M CALL disp_SMA_input LOAD sF, 00 JUMP select_source test_50M: COMPARE sF, switch1 JUMP NZ, test_DCM CALL disp_50MHz_Crystal LOAD sF, 01 JUMP select_source test_DCM: COMPARE sF, switch2 JUMP NZ, test_Ring CALL disp_DCM_Oscillator LOAD sF, 02 JUMP select_source test_Ring: COMPARE sF, switch3 JUMP Z, Ring_select
CALL disp_menu ; more than one switch is set
JUMP warm_start Ring_select: CALL disp_Ring_Osdllator LOAD sF, 03 select_source: OUTPUT sF, source_control_port ;select source control
;Read the most recent values from display on LCD.
;Interrupts will be disabled during the reading of values ;to ensure a clean
;value is obtained when reading multi-byte values.
;Display the count value in the top right of the LCD display ;Up to 999,999,999
DISABLE INTERRUPT
FETCH s2, count0 FETCH s3, count1 FETCH s4, count2 FETCH s5, count3 ENABLE INTERRUPT CALL integer_to_BCD
LOAD s5, 10 CALL LCD_cursor LOAD s6, decimal8 CALL disp_digits JUMP warm_start
Вспомогательные подпрограммы, используемые в основной управляющей программе измерителя частоты цифровых сигналов
Подпрограмма отображения результатов измерения на ЖК-дисплее осуществляет вывод текущего значения частоты входного сигнала, вычисляемого на основании данных, считанных из соответствующих ячеек СОЗУ. Исходный текст этой подпрограммы на языке ассемблера имеет следующий вид:
; Display frequency value on LCD display
;Registers used s0,s1,s4,s5,sE,sF
disp_digits: LOAD sF, FF ; set blanking flag
LOAD sE, character_space ; scaling character for MHz,
; KHz or Hz
FETCH s5, decimal8 ; 100MHz digit
CALL zero_test
CALL disp_digit
FETCH s5, decimal7 ; 10MHz digit
CALL zero_test
CALL disp_digit
FETCH s5, decimal6 ; 1MHz digit
CALL zero_test
CALL disp_digit
COMPARE sF, FF ; check if any MHz were active
JUMP Z, khz_space
LOAD s5, character_stop
CALL LCD_write_data
LOAD sE, character_M
JUMP khz_digits
khz_space: LOAD s5, character_space
CALL LCD_write_data
khz_digits: FETCH s5, decimal5 ; 100KHz digit
CALL zero_test
;copy cycle count to register set ;[s5,s4,s3,s2]
; convert last 32-bit value ; to BCD digits ; Line 1 position 0
; up to 999,999,999 Hz
CALL disp_digit
FETCH s5, decimal4 ; 10KHz digit
CALL zero_test
CALL disp_digit
FETCH s5, decimal3 ; 1KHz digit
CALL zero_test
CALL disp_digit
COMPARE sE, character_M ; check if any MHz were active
JUMP Z, hz_space
COMPARE sF, FF ; check if any KHz were active
JUMP Z, hz_space
LOAD s5, character_stop
CALL LCD_write_data
LOAD sE, character_K
JUMP hz_digits
hz_space: LOAD s5, character_space
CALL LCD_write_data
hz_digits: FETCH s5, decimal2 ; 100KHz digit
CALL zero_test
CALL disp_digit
FETCH s5, decimal1 ; 10KHz digit
CALL zero_test
CALL disp_digit
FETCH s5, decimal0 ; 1KHz digit (always displayed)
ADD s5, character_0 ; convert number to ASCII
CALL LCD_write_data
LOAD s5, character_space
CALL LCD_write_data
LOAD s5, sE
CALL LCD_write_data
LOAD s5, character_H
CALL LCD_write_data
LOAD s5, character_z
CALL LCD_write_data
LOAD s5, character_space ; ensure end of line is clear
CALL LCD_write_data
RETURN
В представленной подпрограмме перед выводом на ЖК-дисплей рассчитанного значения частоты производится проверка наличия в этом числе нулевых старших значащих разрядов, которые не должны отображаться на экране. Кроме того, в данной подпрограмме выполняется автоматическое масштабирование единиц измерения частоты в зависимости от величины полученного результата вычислений. Результаты измерений могут отображаться в герцах (Гц), килогерцах (кГц) и мегагерцах (МГц). Для реализации функции контроля нулей в старших значащих разрядах выводимого значения используется ряд специальных подпрограмм:
; Check digit for zero
If not zero then clear blanking flag (sF=00)
zero_test: COMPARE s5, 00 RETURN Z LOAD sF, 00 RETURN
; Display single digit at current position or space
Display single digit at current position or space if blanking (sF=FF) is active
disp_digit: COMPARE sF, FF JUMP Z, blank_digit
ADD s5, character_0 ;convert number to ASCII
CALL LCD_write_data
RETURN
; Blanking digit
blank_digit: LOAD s5, character_space CALL LCD_write_data RETURN
Подпрограмма конвертирования 32-разрядного двоичного значения в 40-разрядный (десятизначный) двоично-десятичный код используется для преобразования результатов измерения в формат, предназначенный для отображения на ЖК-дисплее. Исходный текст этой подпрограммы на языке ассемблера имеет следующий вид:
; 32-bit integer to BCD conversion
;Registers used s0,s2,s3,s4,s5,s6,s7,s8,s9,sA,sB,sC,sD,sE,sF
integer_to_BCD: LOAD sE, 0A ;10 digits to be formed
from value upto 4294967295 LOAD sF, decimal0 ;pointer for LS-Digit
int_to_BCD_loop: CALL divide_32bit_by_10
STORE s1, (sF) ;remainder becomes digit value
ADD sF, 01 ;move to next most significant digit
SUB sE, 01 ;one less digit to compute
JUMP NZ, int_to_BCD_loop RETURN
В процессе преобразования 32-разрядного двоичного значения в 40-разрядный (десятизначный) двоично-десятичный код применяется операция деления 32-разрядного двоичного числа на 10. Эта операция реализуется с помощью соответствующей подпрограммы, исходный текст которой выглядит следующим образом:
;Divide 32-bit binary integer by 10
The value to be divided is held in register set [s5,s4,s3,s2]
and this is where the result is returned to.
At then end of the integer division the remainder in the
range 0 to 9
win be in register s1,
Registers used s0, s2,s3,s4,s5,s6,s7,s8,s9,sA,sB,sC,sD
de_ divid 2bit_by_10: LOAD sA, s2 ;copy input value to set
;[sD,sC,sB,sA]
LOAD sB, s3
LOAD sC, s4
LOAD sD, s5
LOAD s2, 00 ;clear result
LOAD s3, 00
LOAD s4, 00
LOAD s5, 00
LOAD s9, A0 ;initialise '10' value into msb's
;of set [s9,s8,s7,s6]
LOAD s8, 00
LOAD s7, 00
LOAD s6, 00
LOAD s0, 1D ;29 subtract and shift iterations
;to be performed
div10_loop: SUB sA, s6 ;perform 32-bit subtract
;[sD,sC,sB,sA]-[s9,s8,s7,s6]
SUBCY sB, s7
SUBCY sC, s8
SUBCY sD, s9
JUMP C, div10_restore
SL1 s2 ;shift '1' into result
JUMP div10_shifts
div10_restore: ADD sA, s6 ;perform 32-bit addition
;[sD,sC,sB,sA] + [s9,s8,s7,s6]
ADDCY sB, s7
ADDCY sC, s8
ADDCY sD, s9
SL0 s2 ;shift '0' into result
div10_shifts: SLA s3 ;complete 32-bit shift left
SLA s4
SLA s5
SR0 s9 ;divide '10' value by 2
;(shift right 1 place)
SRA s8
SRA s7
SRA s6
SUB s0, 01 ;count iterations
JUMP NZ, div10_loop
LOAD s1, sA ;remainder of division
RETURN
В группу подпрограмм, используемых для отображения статической текстовой информации на ЖК-дисплее, входят программные модули, выполняющие вывод соответствующих сообщений. К этой же группе относится подпрограмма отображения меню выбора входов. Каждый из этих программных модулей содержит совокупность инструкций вывода соответствующих последовательностей символов. Ниже приведены ассемблерные коды данных подпрограмм:
;LCD text messages
Display 'PicoBlaze' on LCD at current cursor position
disp_PicoBlaze: LOAD s5, character_P CALL LCD_write_data LOAD s5, character_i CALL LCD_write_data LOAD s5, character_c CALL LCD_write_data LOAD s5, character_o CALL LCD_write_data LOAD s5, character_B CALL LCD_write_data LOAD s5, character_l CALL LCD_write_data LOAD s5, character_a CALL LCD_write_data LOAD s5, character_z CALL LCD_write_data LOAD s5, character_e CALL LCD_write_data RETURN
;Display 'Frequency' on LCD at current cursor position
disp_Frequency: LOAD s5, character_F CALL LCD_write_data LOAD s5, character_r CALL LCD_write_data LOAD s5, character_e CALL LCD_write_data LOAD s5, character_q CALL LCD_write_data LOAD s5, character_u CALL LCD_write_data LOAD s5, character_e CALL LCD_write_data LOAD s5, character_n CALL LCD_write_data LOAD s5, character_c CALL LCD_write_data LOAD s5, character_y CALL LCD_write_data RETURN
;Display 'Counter' on LCD at current cursor position
disp_Counter: LOAD s5, character_C CALL LCD_write_data LOAD s5, character_o CALL LCD_write_data LOAD s5, character_u CALL LCD_write_data LOAD s5, character_n CALL LCD_write_data LOAD s5, character_t CALL LCD_write_data LOAD s5, character_e CALL LCD_write_data LOAD s5, character_r CALL LCD_write_data RETURN
;Display version number on LCD at current cursor position
disp_version: LOAD s5, character_v CALL LCD_write_data LOAD s5, character_1 CALL LCD_write_data LOAD s5, character_stop CALL LCD_write_data LOAD s5, character_0 CALL LCD_write_data LOAD s5, character_0 CALL LCD_write_data RETURN
;Display 'SMA input' at current cursor position
disp_SMA_input: LOAD s5, character_S CALL LCD_write_data LOAD s5, character_M CALL LCD_write_data LOAD s5, character_A CALL LCD_write_data LOAD s5, character_space CALL LCD_write_data LOAD s5, character_i CALL LCD_write_data LOAD s5, character_n CALL LCD_write_data LOAD s5, character_p CALL LCD_write_data LOAD s5, character_u CALL LCD_write_data LOAD s5, character_t CALL LCD_write_data LOAD sF, 06 JUMP disp_spaces
;Display '50MHz Crystal' at current cursor position
disp_50MHz_Crystal: LOAD s5, character_5 CALL LCD_write_data LOAD s5, character_0 CALL LCD_write_data LOAD s5, character_M CALL LCD_write_data LOAD s5, character_H CALL LCD_write_data LOAD s5, character_z CALL LCD_write_data LOAD s5, character_space CALL LCD_write_data LOAD s5, character_C CALL LCD_write_data LOAD s5, character_r CALL LCD_write_data LOAD s5, character_y CALL LCD_write_data LOAD s5, character_s CALL LCD_write_data LOAD s5, character_t CALL LCD_write_data LOAD s5, character_a CALL LCD_write_data LOAD s5, character_l CALL LCD_write_data LOAD sF, 02 JUMP disp_spaces
;Display 'DCM oscillator' at current cursor position
disp_DCM_Oscillator: LOAD s5, character_D CALL LCD_write_data LOAD s5, character_C CALL LCD_write_data LOAD s5, character_M CALL LCD_write_data
disp_Oscillator: LOAD s5, character_space CALL LCD_write_data LOAD s5, character_O CALL LCD_write_data LOAD s5, character_s CALL LCD_write_data LOAD s5, character_c CALL LCD_write_data LOAD s5, character_i CALL LCD_write_data LOAD s5, character_l CALL LCD_write_data CALL LCD_write_data LOAD s5, character_a CALL LCD_write_data LOAD s5, character_t CALL LCD_write_data LOAD s5, character_o CALL LCD_write_data LOAD s5, character_r CALL LCD_write_data LOAD s5, character_space CALL LCD_write_data RETURN
;Display 'Ring oscillator' at current cursor position
disp_Ring_Oscillator: LOAD s5, character_R CALL LCD_write_data LOAD s5, character_i CALL LCD_write_data LOAD s5, character_n CALL LCD_write_data LOAD s5, character_g CALL LCD_write_data
JUMP disp_Oscillator
Display spaces at current cursor position Number of spaces to be specified in register sF
disp_spaces: COMPARE sF, 00 RETURN Z
LOAD s5, character_space CALL LCD_write_data SUB sF, 01 JUMP disp_spaces
Display switch setting menu on entire display.
;Line 1 position 0
;Line 2 position 0
disp_menu: LOAD s5, 10 CALL LCD_cursor LOAD s5, character_R CALL LCD_write_data LOAD s5, character_i CALL LCD_write_data LOAD s5, character_n CALL LCD_write_data LOAD s5, character_g CALL LCD_write_data LOAD s5, character_space CALL LCD_write_data LOAD s5, character_D CALL LCD_write_data LOAD s5, character_C CALL LCD_write_data LOAD s5, character_M CALL LCD_write_data LOAD s5, character_space CALL LCD_write_data LOAD s5, character_5 CALL LCD_write_data LOAD s5, character_0 CALL LCD_write_data LOAD s5, character_M CALL LCD_write_data LOAD s5, character_space CALL LCD_write_data LOAD s5, character_S CALL LCD_write_data LOAD s5, character_M CALL LCD_write_data LOAD s5, character_A CALL LCD_write_data LOAD s5, 20 CALL LCD_cursor LOAD s5, character_space CALL LCD_write_data LOAD s5, character_S CALL LCD_write_data LOAD s5, character_W CALL LCD_write_data LOAD s5, character_3 CALL LCD_write_data LOAD s5, character_space CALL LCD_write_data LOAD s5, character_S CALL LCD_write_data LOAD s5, character_W CALL LCD_write_data LOAD s5, character_2 CALL LCD_write_data LOAD s5, character_space CALL LCD_write_data LOAD s5, character_S CALL LCD_write_data LOAD s5, character_W CALL LCD_write_data LOAD s5, character_1 CALL LCD_write_data LOAD s5, character_space CALL LCD_write_data LOAD s5, character_S CALL LCD_write_data LOAD s5, character_W CALL LCD_write_data LOAD s5, character_0 CALL LCD_write_data RETURN
Подпрограммы формирования задержек предназначены для реализации необходимых временных задержек различной длительности в процессе выполнения основной управляющей программы и вызываемых подпрограмм. В данную группу входят подпрограммы формирования задержек длительностью 1 мкс, 40 мкс, 1мс, 20 мс и 1 с, исходный текст которых выглядит следующим образом:
;Software delay routines
Delay of 1us.
Registers used s0
delay_1us: LOAD s0, delay_1us_constant wait_1us: SUB s0, 01
JUMP NZ, wait_1us RETURN
Delay of 40us.
Registers used s0, s1
delay_40us: LOAD s1, 28 ; 40 x 1us = 40us
wait_40us: CALL delay_1us SUB s1, 01
JUMP NZ, wait_40us RETURN
Delay of 1ms.
Registers used s0, s1, s2
delay_1ms: LOAD s2, 19 ; 25 x 40us = 1ms
wait_1ms: CALL delay_40us SUB s2, 01
JUMP NZ, wait_1ms RETURN
Delay of 20ms.
Delay of 20ms used during initialisation.
Registers used s0, s1, s2, s3
delay_20ms: LOAD s3, 14 ; 20 x 1ms = 20ms
wait_20ms: CALL delay_1ms SUB s3, 01
JUMP NZ, wait_20ms RETURN
Delay of approximately 1 second.
Registers used s0, s1, s2, s3, s4
delay_1s: LOAD s4, 32 ;50 x 20ms = 1000ms wait_1s: CALL delay_20ms SUB s4, 01 JUMP NZ, wait_1s RETURN
В подпрограмме формирования задержки длительностью 1 мкс используется параметр delay_1us_constant, значение которого было определено в блоке инициализации. Задержка длительностью 40 мкс создается путем циклического вызова подпрограммы формирования задержки 1 мкс. В свою очередь, подпрограмма задержки 40 мкс используется при создании задержки длительностью 1 мс. Формирование интервала задержки длительностью 20 мс осуществляется путем соответствующего числа вызовов подпрограммы задержки 1 мс. Задержка длительностью 1 с создается с помощью необходимого числа обращений к подпрограмме задержки 20 мс.
Группу подпрограмм управления работой жидкокристаллического дисплея образуют программные модули, реализующие протокол взаимодействия микропроцессорного блока с интерфейсом дисплея. В данную группу, в частности, входят подпрограммы записи четырех- и восьмиразрядных инструкций, записи и чтения данных, инициализации дисплея, очистки экрана, управления курсором. Исходный текст указанных подпрограмм на языке ассемблера выглядит следующим образом:
;LCD Character Module Routines
;Pulse LCD enable signal 'E' high for greater than 230ns (1us is used).
;Register s4 should define the current state of the LCD output port.
;Registers used s0, s4
LCD_pulse_E: XOR s4, LCD_E ;E=1 OUTPUT s4, LCD_output_port CALL delay_1us
XOR s4, LCD_E ;E=0
OUTPUT s4, LCD_output_port RETURN
;Write 4-bit instruction to LCD display.
;The 4-bit instruction should be provided in the upper 4-bits of register s4.
;Note that this routine does not release the master enable but as it is only
;used during initialisation and as part of the 8-bit instruction write it
;should be acceptable.
;Registers used s4
LCD_write_inst4: AND s4, F8 ;Enable=1 RS=0 Instruction, RW=0 Write, E=0
OUTPUT s4, LCD_output_port ;set up RS and RW >40ns before enable pulse
CALL LCD_pulse_E RETURN
Write 8-bit instruction to LCD display.
The 8-bit instruction should be provided in register s5.
Instructions are written using the following sequence
Upper nibble
wait >1us
Lower nibble
wait >40us
;Registers used s0, s1, s4, s5
LCD_write_inst8: LOAD s4, s5 AND s4, F0
OR s4, LCD_drive
CALL LCD_write_inst4
CALL delay_1us
LOAD s4, s5
SL1 s4
SL0 s4
SL0 s4
SL0 s4
CALL LCD_write_inst4 CALL delay_40us LOAD s4, F0
Enable=0 RS=0 Instruction, RW=0 Write, E=0 Enable=1
write upper nibble wait >1us
select lower nibble with
Enable=1
RS=0 Instruction
RW=0 Write
E=0
write lower nibble wait >40us
Enable=0 RS=0 Instruction, RW=0 Write, E=0
OUTPUT s4, LCD_output_port ;Release master enable RETURN
Write 8-bit data to LCD display.
The 8-bit data should be provided in register s5.
Data bytes are written using the following sequence
Upper nibble
wait >1us
Lower nibble
wait >40us
Registers used s0, s1, s4, s5
LCD_write_data: LOAD s4, s5 AND s4, F0
OR s4, 0C
OUTPUT s4, LCD_output fore enable pulse
CALL LCD_pulse_E
CALL delay_1us
LOAD s4, s5
SL1 s4
SL1 s4
SL0 s4
SL0 s4
OUTPUT s4, LCD_output fore enable pulse
CALL LCD_pulse_E CALL delay_40us LOAD s4, F0
Enable=0 RS=0 Instruction, RW=0 Write, E=0 Enable=1 RS=1 Data, RW=0 Write, E=0 .port ;set up RS and RW >40ns be-
write upper nibble wait >1us
select lower nibble with
Enable=1
RS=1 Data
RW=0 Write
E=0
.port ;set up RS and RW >40ns be-
write lower nibble wait >40us
Enable=0 RS=0 Instruction, RW=0 Write, E=0 OUTPUT s4, LCD_output_port ; Release master enable
Read 8-bit data from LCD display.
The 8-bit data will be read from the current LCD memory address and will be returned in register s5.
It is advisable to set the LCD address (cursor position) before using the data read for the first time otherwise the display may generate invalid data on the first read.
Data bytes are read using the following sequence Upper nibble wait >1us Lower nibble wait >40us
Registers used s0, s1, s4, s5
LCD_read_data8: LOAD s4, 0E ;Enable=1 RS=1 Data, RW=1 ;Read, E=0
OUTPUT s4, LCD_output_port ;set up RS and RW >40ns before enable pulse
XOR s4, LCD_E ;E=1
OUTPUT s4, LCD_output_port
CALL delay_1us ;wait >260ns to access data
INPUT s5, LCD_input_port ;read upper nibble
XOR s4, LCD_E ;E=0
OUTPUT s4, LCD_output_port
CALL delay_1us ;wait >1us
XOR s4, LCD_E ;E=1
OUTPUT s4, LCD_output_port
CALL delay_1us ; wait >260ns to access data
INPUT s0, LCD_input_port ; read lower nibble
XOR s4, LCD_E ; E=0
OUTPUT s4, LCD_output_port
AND s5, F0 ; merge upper and lower nibbles
SR0 s0
SR0 s0
SR0 s0
SR0 s0
OR s5, s0
LOAD s4, 04 ; Enable=0 RS=1 Data, RW=0
; Write, E=0
OUTPUT s4, LCD_output_port ; Stop reading 5V device
; and release
;master enable
CALL delay_40us ; wait >40us
RETURN
;Reset and initialise display to communicate using 4-bit data
mode
;Includes routine to clear the display.
;Requires the 4-bit instructions 3,3,3,2 to be sent with suitable
delays
following by the 8-bit instructions to set up the display.
; 28 = '001' Function set, '0' 4-bit mode, '1' 2-line, '0' 5x7 dot matrix, 'xx'
; 06 = '000001' Entry mode, '1' increment, '0' no display shift ; 0C = '00001' Display control, '1' display on, '0' cursor off, '0' cursor blink off
; 01 = '00000001' Display clear
Registers used s0, s1, s2, s3, s4
LCD_reset: CALL delay_20ms ; wait more that 15ms for display ; to be ready
LOAD s4, 30 CALL LCD_write_inst CALL delay_20ms CALL LCD_write_inst CALL delay_1ms CALL LCD_write_inst CALL delay_40us LOAD s4, 20 CALL LCD_write_inst CALL delay_40us LOAD s5, 28 CALL LCD_write_inst LOAD s5, 06 CALL LCD_write_inst LOAD s5, 0C CALL LCD_write_inst LCD_clear: LOAD s5, 01 CALL LCD_write_inst
; send '3'
; wait >4.1ms ; send '3'
; wait >100us ; send '3'
; wait >40us
; send '2'
; wait >40us ; Function set
; Entry mode
; Display control
; Display clear
CALL delay_1ms ; wait >1.64ms for display to clear
CALL delay_1ms
RETURN
Position the cursor ready for characters to be written.
The display is formed of 2 lines of 16 characters and each position has a corresponding address as indicated below.
Character position 0 1 23 456789 10 11 12 13 14 15
Line 1 — 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
RETURN
Line 2— C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
;This routine will set the cursor position using the value provided ;in register s5. The upper nibble will define the line and the lower ;nibble the character position on the line.
Example s5 = 2B will position the cursor on line 2 position 11
Registers used s0, s1, s2, s3, s4
; test for line 1
LCD_cursor: TEST s5, 10 JUMP Z, set_line2 AND s5, 0F
OR s5, 80
CALL LCD_write_inst8 RETURN set_line2: AND s5, 0F
OR s5, C0
CALL LCD_write_inst8 RETURN
; make address in range 80 to 8F ; for line 1
; instruction write to set cursor
; make address in range C0 to CF ; for line 2
; instruction write to set cursor
Алгоритм и исходный текст подпрограммы обработки прерываний для измерителя частоты цифровых сигналов
Алгоритм подпрограммы обработки прерываний, используемой в микропроцессорном блоке измерителя частоты цифровых сигналов, показан на рис. 9.
В начале процедуры обслуживания прерывания выполняется сохранение текущего содержимого всех регистров общего назначения исполнительного модуля КСРЭМ3 в соответствующих ячейках СОЗУ. После этого определяется режим работы (состояние) каждого канала измерительного блока. Затем в выходные порты, к которым подключен блок светодиодных индикаторов, производится запись информации, которая соответствует номеру активного канала измерительного блока. Далее осуществляется побайтное чтение содержимого соответствующего 32-разрядного счетчика в регистры общего назначения модуля КСР8М3. В последующей части процедуры обслуживания прерывания производится сброс этого счетчика и перезапись информации из регистров общего назначения в ячейки СОЗУ, предназначенные для хранения результатов измерения в двоичном формате. Завершает подпрограмму обработки прерывания последовательность команд, восстанавливающих первоначальное содержимое регистров общего назначения, которое было сохранено в соответствующих ячейках СОЗУ, и устанавливающих режим разрешения последующих прерываний.
Сигналы прерывания в рассматриваемом устройстве генерируются периодически с интервалом, равным 1 с. При этом следует обратить внимание на то, что первые четыре прерывания, формируемые сразу после подачи напряжения питания, игнорируются. Процедура обслуживания прерывания в этих случаях выполняет только обнуление 32-разрядных счетчиков, которые входят в состав измерительного блока. Содержимое этих счетчиков при этом не считывается и не сохраняется в ячейках СОЗУ. Такое решение обеспечивает достоверность результатов измерения частоты в рассматриваемом устройстве.
В состав подпрограммы обработки прерываний входит следующая последовательность инструкций:
;Interrupt Service Routine
ISR: STORE s0, preserve_s0 ;preserve registers
STORE s1, preserve_s1 STORE s2, preserve_s2 STORE s3, preserve_s3 STORE s4, preserve_s4 STORE s5, preserve_s5 STORE s6, preserve_s6 STORE s7, preserve_s7 STORE s8, preserve_s8 STORE s9, preserve_s9 STORE sA, preserve_sA STORE sB, preserve_sB STORE sC, preserve_sC STORE sD, preserve_sD STORE sE, preserve_sE STORE sF, preserve_sF
;Ignore the first 4 interrupts except to clear the counter. ;This will ensure a clean start up after reset.
FETCH s0, ISR_count ;test to see if more that 4
;interrupts have occurred
COMPARE s0, 04 JUMP Z, normal_isr
ADD s0, 01 ;increment ISR counter
;until reaching 4
Check which counter to clear if bit0 is Low then A is counting JUMP Z, clear_B_count clear_A_count: LOAD s0, a_count_reset ; clear the active counter JUMP clear_counter clear_B_count: LOAD s0, b_count_reset ; clear the active counter clear_counter: OUTPUT s0, count_resetport ; reset counter with ; pulse
LOAD s0, 00 ; end reset pulse to either
; counter
OUTPUT s0, count_resetport JUMP restore_reg
STORE s0, ISR_count INPUT s0, status_port TEST s0, AB_switch
Normal ISR Routine
Read the new counter value and then clear it ready to start again
normal_isr: INPUT s0, status_port TEST s0, AB_switch JUMP Z, capture_B_count capture_A_count: LOAD s0, F0
OUTPUT s0, LED_port INPUT sC, A_count0_port
; test for active counter ; if bit is low then A is counting
; set LEDs to indicate active ; counter
; read counter A into ; [sF,sE,SD,sC]
INPUT sD, A_count1_port
INPUT sE, A_count2_port
INPUT sF, A_count3_port
LOAD s0, a_count_reset ; reset counter A
OUTPUT s0, count_resetport
JUMP counters_read
capture_B_count: LOAD s0, 0F
OUTPUT s0, LED_port INPUT sC, B_count0_port
; set LEDs to indicate active ; counter
; read counter A into ; [sF,sE,SD,sC]
INPUT sD, B_count1_port INPUT sE, B_count2_port INPUT sF, B_count3_port LOAD s0, b_count_reset ; reset counter B
OUTPUT s0, count_resetport counters_read LOAD s0, 00 ; end reset pulse to either
; counter
OUTPUT s0, count_resetport
STORE sC, count0 STORE sD, count1 STORE sE, count2 STORE sF, count3
; store new counter value
;Restore registers and end ISR
restore_reg: FETCH sF, preserve_sF ; restore registers FETCH sE, preserve_sE FETCH sD, preserve_sD FETCH sC, preserve_sC FETCH sB, preserve_sB FETCH sA, preserve_sA FETCH s9, preserve_s9 FETCH s8, preserve_s8
FETCH s7, preserve_s7 FETCH s6, preserve_s6 FETCH s5, preserve_s5 FETCH s4, preserve_s4 FETCH s3, preserve_s3 FETCH s2, preserve_s2 FETCH s1, preserve_s1 FETCH s0, preserve_s0 RETURNI ENABLE
Сразу после исходного текста подпрограммы обслуживания прерывания приведем следующие директивы и команды, которые предназначены для определения вектора обработки прерывания:
;Interrupt vector
ADDRESS 3FF JUMP ISR ;End of Program
В соответствии с правилами, установленными для версии микропроцессорного ядра семейства PicoBlaze, которая применяется в проектах, реализуемых на основе ПЛИС семейств Spartan-3, Spartan-3E, Virtex-II, Virtex-IIPRO и Virtex-4, код вектора обработки прерывания должен располагаться по адресу 3FF [2, 7].
Заключение
Для аппаратной реализации рассмотренного проекта измерителя частоты цифровых сигналов без внесения в него каких-либо изменений достаточно выполнить стандартную процедуру загрузки конфигурационной последовательности, которая содержится в файле frequency_counter.bit., в ПЛИС XC3S500E инструментального модуля Xilinx Spartan-3E Starter Board [11]. Данный файл может также использоваться для программирования конфигурационного ППЗУ, расположенного на плате этого инструментального модуля [2]. Для выполнения процесса записи указанной конфигурационной последовательности в кристалл или ППЗУ целесообразно использовать USB-кабель, входящий в состав инструментального комплекта Xilinx Spartan-3E Starter Kit, и встроенную схему загрузочного кабеля, которая присутствует на плате отладочного модуля. Чтобы ускорить процесс аппаратной реализации рассмотренного проекта, следует воспользоваться командным файлом install_frequency_counter.bat, при запуске которого процедура загрузки конфигурационной последовательности, представленная в файле frequency_counter.bit, выполняется автоматически в пакетном режиме.
Если в исходный текст микропрограммного обеспечения измерителя частоты цифровых сигналов необходимо внести изменения или дополнения, соответствующие условиям решаемой задачи, то после коррекции ассемблерного кода следует повторно выполнить процесс его трансляции. При сохранении неизменной аппаратной
части рассматриваемого устройства для записи новой версии управляющей программы рекомендуется использовать загрузчик JTAG Program Loader, который входит в состав архива исходных модулей ядра PicoBlaze, предназначенного для применения в проектах, реализуемых на основе ПЛИС семейств Spartan-3, Spartan-3E, Virtex-II, Virtex-IIPRO и Virtex-4. Чтобы воспользоваться этим загрузчиком, необходимо при трансляции исходного текста микропрограммного обеспечения использовать модифицированные варианты шаблонов описания содержимого ППЗУ JTAG_Loader_ROM_form.vhd иJTAG_Loader_ROM_form.v [2, 7]. Сформированный в результате трансляции код управляющей программы может быть записан непосредственно в программную память ядра PicoBlaze через порт JTAG-интерфейса инструментального модуля с помощью загрузчика JTAG Program Loader и того же кабеля, который использовался для загрузки конфигурационной последовательности из файла frequency_counter.bit.
В тех случаях, когда требуется внести изменения не только в исходный текст микропрограммного обеспечения, но и в описание аппаратной части измерителя частоты цифровых сигналов (например, добавить новые блоки), необходимо повторно выполнить
всю последовательность этапов проектирования встраиваемых 8-разрядных микропроцессорных систем на основе ядер семейства
PicoBlaze [2], ■
Литература
1, Зотов В, Цифровой генератор сигнала с перестраиваемой частотой, реализуемый на базе инструментального комплекта Spartan-3E Starter Kit фирмы Xilinx // Компоненты и технологии, 2006, № 11-12,
2, Зотов В, Проектирование встраиваемых микропроцессорных систем на основе ПЛИС фирмы Xilinx, М,: Горячая линия — Телеком, 2006,
3, Зотов В, PicoBlaze — семейство восьмиразрядных микропроцессорных ядер, реализуемых на основе ПЛИС фирмы Xilinx // Компоненты и технологии, 2003, № 4,
4, Зотов В, Система команд микропроцессорного ядра PicoBlaze, реализуемого на основе ПЛИС семейств Spartan-II, Spartan-IIE, Virtex, Virtex-E // Компоненты и технологии, 2003, № 5,
5, Зотов В, Особенности микропроцессорного ядра PicoBlaze, предназначенного для применения в проектах, реализуемых на основе ПЛИС семейства Virtex-II // Компоненты и технологии,
2003, № 6,
6, Зотов В, Особенности микропроцессорного ядра PicoBlaze, предназначенного для применения
в проектах, реализуемых на основе ПЛИС семейства CoolRunner-II // Компоненты и технологии. 2003. № 7.
7. Зотов В. Особенности микропроцессорного ядра PicoBlaze, предназначенного для применения в проектах, реализуемых на основе ПЛИС семейств Spartan-3, Virtex-II и Virtex-IIPRO // Компоненты и технологии. 2005. № 5-6.
8. Зотов В. MicroBlaze — семейство тридцатидвухразрядных микропроцессорных ядер, реализуемых на основе ПЛИС фирмы Xilinx // Компоненты и технологии. 2003. № 9.
9. Зотов В. Система команд микропроцессорного ядра MicroBlaze // Компоненты и технологии.
2004. № 1-3.
10. Зотов В. Организация памяти микропроцессорного ядра MicroBlaze // Компоненты и технологии. 2004. № 5.
11. Зотов В. Новый инструментальный комплект Spartan-3E Starter Kit для практического освоения методов проектирования встраиваемых микропроцессорных систем на основе ПЛИС семейств FPGA фирмы Xilinx // Компоненты и технологии. 2006. № 10.
12. Бибило П. Н. Основы языка VHDL. М.: Солон-Р, 2000.
13. Бибило П. Н. Синтез логических схем с использованием языка VHDL. М.: Солон-Р, 2002.
14. Уэйкерли Дж. Ф. Проектирование цифровых устройств. Том 1. М.: Постмаркет, 2002.