; Simple Picoblaze application for Spartan Starter Board ; Jim Duckworth, WPI. October 30th, 2005 ; VHDL "ece574_template.vhd", "ece574_rom.vhd", "ece574_rom" ; Port definitions ; ; ; ==================================================================== DIPSW_port DSIN $04 ; Dip Switches LEDS_port DSOUT $02 ; UART ports tx_half_full EQU 1 ; Transmitter half full - bit0 tx_full EQU 2 ; FIFO full - bit1 rx_half_full EQU 4 ; Receiver half full - bit2 rx_full EQU 8 ; FIFO full - bit3 rx_data_present EQU $10 ; data present - bit4 ; RS232 UART Port UART_status_port DSIN $01 ; UART status IN UART_read_port DSIN $02 ; UART Rx data IN UART_write_port DSOUT $01 ; UART Tx data OUT ; ; ==================================================================== ; ; Special Register usage ; mode_reg EQU sF ; operating mode of processor ; uart_pointer EQU sE ; used to store pointer string ; ; Two registers to form a 16-bit counter used to count ; interrupt pulses generated at 1us intervals. ; int_counter_lsb EQU sD ; lower 8-bits int_counter_msb EQU sC ; upper 8-bits ; uart_data EQU s8 ; used to pass data to and from UART ; ; ===================================================== ; scratch pad memory locations temp EQU 5 ; used to save other values ; ; ; UART character strings will be stored in scratch pad memory ending in carriage RET. ; A string can be up to 16 characters with the start location defined by this . ; string_start EQU $10 ; Initialise the system ; cold_start: LOAD s0, $33 OUT s0, LEDS_port ; turn all devices OFF CALL Delay250ms CALL Delay250ms CALL Delay250ms CALL Delay250ms LOAD s0, $55 OUT s0, LEDS_port ; turn all devices OFF CALL Delay250ms LOAD s2,$75 STORE s2, temp ; save value FETCH s3,temp ; retrieve value CALL send_ece574 ; send "ECE574" to RS232 ; ; LOAD int_counter_lsb, 0 ; clear 'us' interrupt counter ; LOAD int_counter_msb, 0 ; ; ENABLE INTERRUPT ;enable the 1us interrupts ; ; ; Start of the main program loop. ; main_loop: IN s1, DIPSW_port ; read switches OUT s1, LEDS_port ; turn on leds CALL Delay250ms JUMP main_loop ; ; ==================================================================================================== ; ========================================================================================== ; UART routines read_from_UART: ; Read one character from the UART ; ; Character read will be returned in a register called 'uart_data' ; ; The routine first tests the receiver FIFO buffer to see if data is present. ; If the FIFO is empty, the routine just returns. ; ; Registers used s0 and uart_data ; IN s0, UART_status_port; test Rx_FIFO buffer TEST s0, rx_data_present JUMP Z, read_from_uart_end IN s1, UART_read_port ; read from FIFO LOAD uart_data, s1 read_from_uart_end: RET send_to_UART: ; Transmit one character to the UART ; ; Character supplied in register called 'uart_data'. ; ; The routine first tests the transmit FIFO buffer to see if it is full. ; ; Registers used s0 ; IN s0, UART_status_port; test Tx_FIFO buffer TEST s0, tx_full JUMP NZ, send_to_UART LOAD s0, uart_data OUT s0, UART_write_port RET ; ========================================================================================== ; Transmit ASCII string to UART ; ; An ASCII string must be provided in scratch pad memory commencing at the ; location specified by a named 'string_start'. The string must ; end with a carriage return and LF. ; ; Registers used s1 and 'uart_data'. ; s0 is then used in subroutine 'send_to_UART' ; transmit_string: LOAD s1, string_start ; locate start of string next_char_tx: FETCH uart_data, ( s1 ) ; read character from memory CALL send_to_UART ; transmit character COMP uart_data, character_LF; test for last character RET Z ADD s1, 1 ; move to next character JUMP next_char_tx ; ========================================================================================== ; Send 'ECE574' to the UART ; send_ece574: LOAD UART_data, character_CR; start new line CALL send_to_UART LOAD UART_data, character_LF CALL send_to_UART LOAD UART_data, character_uE CALL send_to_UART LOAD UART_data, character_uC CALL send_to_UART LOAD UART_data, character_uE CALL send_to_UART LOAD UART_data, character_5 CALL send_to_UART LOAD UART_data, character_7 CALL send_to_UART LOAD UART_data, character_4 CALL send_to_UART LOAD UART_data, character_CR CALL send_to_UART RET ; ========================================================================================== delay1us: ; 1us delay loop - assumes 50MHz clock LOAD s0, 12 ; need to check this delay delay1us1: SUB s0, $01 JUMP NZ, delay1us1 RET ; ========================================================================================== delay16ms: ; approx. 16ms delay loop - assumes 50MHz clock LOAD s2, $50 ; 80 decimal delay16ms0: LOAD s1, $C8 ; 200 decimal (need to check this delay) delay16ms1: CALL delay1us SUB s1, 1 JUMP NZ, delay16ms1 SUB s2, 1 JUMP NZ, delay16ms0 RET ; ========================================================================================== delay250ms: ; approx. 250ms delay loop - assumes 50MHz clock LOAD s3, 16 ; need to check this delay delay250_1: CALL delay16ms SUB s3, $01 JUMP NZ, delay250_1 RET ; ; ========================================================================================== ; ; Interrupt service routine (ISR) ; ; The interrupt is used to increment a 16-bit counter formed with two registers ; called [int_counter_msb,int_counter_lsb]. This provides a count of the number ; of micro-seconds elapsed. The counter is 'free running' in that it will count ; up to 65,535 and then roll over to zero. The count value is then used in other ; parts of the program as required and where it is less time critical. ; ; The ISR only uses the specified counter registers ; ORG $3FC ISR: ADD int_counter_lsb, 1 ; add 1us to 16-bit counter ADDC int_counter_msb, 0 RETI ENABLE ; ; Interrupt vector ; ORG $3FF JUMP ISR ; ; ; Useful constants ; ; ; ASCII table ; character_a EQU $61 character_b EQU $62 character_c EQU $63 character_d EQU $64 character_e EQU $65 character_f EQU $66 character_g EQU $67 character_h EQU $68 character_i EQU $69 character_j EQU $6A character_k EQU $6B character_l EQU $6C character_m EQU $6D character_n EQU $6E character_o EQU $6F character_p EQU $70 character_q EQU $71 character_r EQU $72 character_s EQU $73 character_t EQU $74 character_u EQU $75 character_v EQU $76 character_w EQU $77 character_x EQU $78 character_y EQU $79 character_z EQU $7A character_uA EQU $41 character_uB EQU $42 character_uC EQU $43 character_uD EQU $44 character_uE EQU $45 character_uF EQU $46 character_uG EQU $47 character_uH EQU $48 character_uI EQU $49 character_uJ EQU $4A character_uK EQU $4B character_uL EQU $4C character_uM EQU $4D character_uN EQU $4E character_uO EQU $4F character_uP EQU $50 character_uQ EQU $51 character_uR EQU $52 character_uS EQU $53 character_uT EQU $54 character_uU EQU $55 character_uV EQU $56 character_uW EQU $57 character_uX EQU $58 character_uY EQU $59 character_uZ EQU $5A character_0 EQU $30 character_1 EQU $31 character_2 EQU $32 character_3 EQU $33 character_4 EQU $34 character_5 EQU $35 character_6 EQU $36 character_7 EQU $37 character_8 EQU $38 character_9 EQU $39 character_esc EQU $1B ; esc character character_comma EQU $2C character_dash EQU $2D character_colon EQU $3A character_semi_colon EQU $3B character_less_than EQU $3C character_greater_than EQU $3E character_equals EQU $3D character_space EQU $20 character_CR EQU $0D ; carriage RET character_LF EQU $0A ; line feed character_question EQU $3F ; '?' character_dollar EQU $24 character_BS EQU $08 ; Back Space command character ;