URL
https://opencores.org/ocsvn/light8080/light8080/trunk
Subversion Repositories light8080
[/] [light8080/] [trunk/] [sw/] [tb/] [soc_tb/] [soc_tb.asm] - Rev 74
Compare with Previous | Blame | View Log
;*******************************************************************************; soc_tb.asm -- light8080 SoC basic test bench.;*******************************************************************************; Should be used with SoC core test bench entity vhdl\test\l80soc_tb.vhdl.; Assembler format compatible with TASM for DOS and Linux.;*******************************************************************************; This program will send a few bytes over a looped-back UART, using the UART; interrupt capability and verifying that received and transmitted data match.; It will then try one of the external interrupts, connected to one of the; general purpose outputs.; This minimal test bench relies on an already tested CPU core to do a; This program does not deserve to even be called a 'test' but if if works it; will at least rule out many obvious bug in the SoC core.;*******************************************************************************; DS pseudo-directive; reserve space in bytes, without initializing it#define ds(n) \.org $+nMASK_RX_IRQ: .equ 20hMASK_TX_IRQ: .equ 10hMASK_RX_RDY: .equ 02hMASK_TX_RDY: .equ 01hUART_DATA: .equ 80hUART_STATUS: .equ 81hUART_BAUDL: .equ 82hUART_BAUDH: .equ 83hIRQ_ENABLE: .equ 88hP1IN: .equ 84hP2OUT: .equ 86h;*******************************************************************************.org 0H ; Reset entry pointjmp start ; Skip the rst address area;***** Interrupt vectors in area 0008h-0038h *****************.org 0h+(1*8) ; interrupt vector 1 (IRQ0)jmp isr0.org 0h+(2*8) ; interrupt vector 2eiret.org 0h+(3*8) ; interrupt vector 3 (IRQ1)jmp isr1.org 0h+(4*8) ; interrupt vector 4eiret.org 0h+(5*8) ; interrupt vector 5 (IRQ2)eiret.org 0h+(6*8) ; interrupt vector 6eiret.org 0h+(7*8) ; interrupt vector 7 (IRQ3, UART)int38h: jmp irq_uart ; UART interrupt;***** program entry point *******************************************start: .org 60Hlxi sp,stack; Initialize UART RX and TX bufferslxi h,void_buffershld ptr_txlxi h,rx_buffershld ptr_rxmvi a,00hsta len_rx; Clear all P2 output lines (used to simulate external interrupts)mvi a,00hout P2OUT; Set up interruptsmvi a,0bh ; Enable UART irq plus IRQ0 and IRQ1...out IRQ_ENABLEei ; ...and enable interrupts in the CPU; print hello message to consolelxi h,msg_hellocall print_string; Ok, now the message is being transferred through the looped back; UART, using the UART interrupts, which have the lowest priority.; We have plenty of time to make a few tests on the external interrupt; lines before the message transmission is finished.; The irq routines will leave some data at 'irq_data, each routine a; different value and all non-zero. This is how we know what irq; routines have executed and in which order.; Test IRQ0 alonemvi a,01h ; Initialize irq datasta irq_datamvi a,01h ; Trigger IRQ0out P2OUTtest_irq0:lda irq_datacpi 004h ; Do we see the IRQ test data?jz done_irq0 ; If we do, proceed to next testcpi 001h ; Do we see some other IRQ test data instead?jnz test_fail ; If we do, there's trouble with the irqsjmp test_irq0 ; Keep waiting for some IRQ test datadone_irq0:mvi a,00h ; Deassert all interrupt linesout P2OUT; Test IRQ1 alonemvi a,01h ; Initialize irq datasta irq_datamvi a,02h ; Trigger IRQ1out P2OUTtest_irq1:lda irq_datacpi 002h ; Do we see the IRQ test data?jz done_irq1 ; If we do, proceed to next testcpi 001h ; Do we see some other IRQ test data instead?jnz test_fail ; If we do, there's trouble with the irqsjmp test_irq1 ; Keep waiting for some IRQ test datadone_irq1:xra a ; Deassert all interrupt linesout P2OUT; Test IRQ0 and IRQ1 simultaneouslymvi a,01h ; Initialize irq datasta irq_datamvi a,03h ; Trigger IRQ0 and IRQ1out P2OUT; Sequence IRQ0->IRQ1 will result in (1 << 2) + 1 = 5; Sequence IRQ1->IRQ0 would result in (1 + 1) << 2 = 6; We expect IRQ0->IRQ1, since IRQ0 has higher prioritytest_irq01:lda irq_datacpi 005h ; Do we see the IRQ0->IRQ1 test data?jz done_irq01 ; If we do, proceed to next testcpi 001h ; Do we see some other IRQ test data instead?jnz test_fail ; If we do, there's trouble with the irqsjmp test_irq01 ; Keep waiting for some IRQ test datadone_irq01:xra a ; Deassert all interrupt linesout P2OUT; Ok, the external interrupts have been tested (well, 'tested'). Now; wait for the UART looped-back transmission to end and compare; the data.; Wait until the number of UART received characters equals the length; of the test message.wait_for_message:lda len_rxcpi msg_lenjnz wait_for_message; Compare the TX and RX stringslxi h,rx_bufferlxi d,msg_hellocompare_loop:ldax dcpi '$'jz test_okcmp mjnz test_failinx hinx djmp compare_looptest_ok:mvi a,80h ; Raise 'success' output flag...out P2OUTdone: di ; ...and block here.hlttest_fail:mvi a,40h ; Raise 'failure' flag...out P2OUTjmp done ; ...and block.msg_hello: .text "\n\r\nHello World!$"msg_end: .equ $; compute message length (-1 for the '$' that does not get TX'd)msg_len: .equ msg_end - msg_hello - 1; IRQ0 routine will shift irq_data left twiceisr0: push pswlda irq_datarlcrlcsta irq_datapop psweiret; IRQ1 routine will increment irq_dataisr1: push pswlda irq_dataadi 1sta irq_datapop psweiret;irq_uart: UART interrupt processingirq_uart:push hpush psw; Deal with RX interrupt (if any) first and then the TX interrupt.in UART_STATUS ; Is there new data in the RX register?ani MASK_RX_IRQjz irq_uart_rx_done ; If there isn't, process TX interrupt.; Process UART RX interruptirq_uart_rx:mvi a,MASK_RX_IRQ ; Clear IRQ flag.out UART_STATUSin UART_DATA ; Get RX byte...lhld ptr_rx ; ...and store it in the rx buffer.mov m,ainx hshld ptr_rx ; Update the rx buffer pointer.lda len_rx ; Update RX buffer lengthinr asta len_rx; Note there's no check for RX buffer overrun! we shouldn't need it; here, a runaway condition would be readily apparent in the; simulation, anyway.irq_uart_rx_done:; Ok, RX is done. Now deal with TX irq, if anyin UART_STATUS ; Is the TX buffer re new data in the RX register?ani MASK_TX_IRQjz irq_uart_end ; If there isn't, we're done.; process UART TX interruptirq_uart_tx:mvi a,MASK_TX_IRQ ; Clear IRQ flag.out UART_STATUSlhld ptr_tx ; Get next byte from the TX buffermov a,mcpi '$' ; Did we reach the end of the buffer?jz irq_uart_tx_done ; If we did, we're done here...inx h ; ...otherwise increment the TX pointer...shld ptr_txout UART_DATA ; ...and transmit the data byte.irq_uart_tx_done:irq_uart_end:pop psw ; Done, quit.pop heiret;print_string: print $-terminated string at HLprint_string:; We don't check if there's a transmission going onmov a,m ; Get first character from string...inx h ; ...and move updated string pointer to TXshld ptr_tx ; buffer pointer.cpi '$' ; Kickstart transmission by sending 1st byte...jz print_string_end; ...unless its the end of string marker.out UART_DATA ;print_string_end:ret; data space, placed immediately after object code in memoryirq_data: ds(1)void_buffer: .text "$"ptr_tx: ds(2)ptr_rx: ds(2)len_rx: ds(1)rx_buffer: ds(32)ds(64)stack: ds(2).end
