mirror of
https://github.com/pConst/basic_verilog.git
synced 2025-02-04 07:12:56 +08:00
789 lines
32 KiB
Plaintext
789 lines
32 KiB
Plaintext
/* Symbol Table */
|
|
// BTN_east = CONSTANT: 2
|
|
// BTN_north = CONSTANT: 1
|
|
// BTN_south = CONSTANT: 4
|
|
// BTN_west = CONSTANT: 8
|
|
// ISR = LABEL: 192
|
|
// LED0 = CONSTANT: 1
|
|
// LED1 = CONSTANT: 2
|
|
// LED2 = CONSTANT: 4
|
|
// LED3 = CONSTANT: 8
|
|
// LED4 = CONSTANT: 16
|
|
// LED5 = CONSTANT: 32
|
|
// LED6 = CONSTANT: 64
|
|
// LED7 = CONSTANT: 128
|
|
// LED_port = CONSTANT: 128
|
|
// SPI_adc_conv = CONSTANT: 16
|
|
// SPI_amp_cs = CONSTANT: 8
|
|
// SPI_amp_sdi = CONSTANT: 64
|
|
// SPI_amp_shdn = CONSTANT: 64
|
|
// SPI_control_port = CONSTANT: 8
|
|
// SPI_dac_clr = CONSTANT: 128
|
|
// SPI_dac_cs = CONSTANT: 32
|
|
// SPI_dac_tx_rx = LABEL: 122
|
|
// SPI_init = LABEL: 119
|
|
// SPI_input_port = CONSTANT: 1
|
|
// SPI_output_port = CONSTANT: 4
|
|
// SPI_rom_cs = CONSTANT: 2
|
|
// SPI_sck = CONSTANT: 1
|
|
// SPI_sdi = CONSTANT: 128
|
|
// SPI_sdo = CONSTANT: 128
|
|
// SPI_spare_control = CONSTANT: 4
|
|
// calc_next_sine = LABEL: 94
|
|
// chan_A_lsb = CONSTANT: 0
|
|
// chan_A_msb = CONSTANT: 1
|
|
// chan_B_lsb = CONSTANT: 2
|
|
// chan_B_msb = CONSTANT: 3
|
|
// chan_C_lsb = CONSTANT: 4
|
|
// chan_C_msb = CONSTANT: 5
|
|
// chan_D_lsb = CONSTANT: 6
|
|
// chan_D_msb = CONSTANT: 7
|
|
// cold_start = LABEL: 0
|
|
// dac_reset = LABEL: 162
|
|
// delay_1ms = LABEL: 177
|
|
// delay_1s = LABEL: 187
|
|
// delay_1us = LABEL: 168
|
|
// delay_1us_constant = CONSTANT: 11
|
|
// delay_20ms = LABEL: 182
|
|
// delay_40us = LABEL: 172
|
|
// init_sine_wave = LABEL: 82
|
|
// mult_loop = LABEL: 103
|
|
// next_SPI_dac_bit = LABEL: 123
|
|
// no_mult_add = LABEL: 110
|
|
// s0 = REGISTER: 0
|
|
// s1 = REGISTER: 1
|
|
// s2 = REGISTER: 2
|
|
// s3 = REGISTER: 3
|
|
// s4 = REGISTER: 4
|
|
// s5 = REGISTER: 5
|
|
// s6 = REGISTER: 6
|
|
// s7 = REGISTER: 7
|
|
// s8 = REGISTER: 8
|
|
// s9 = REGISTER: 9
|
|
// sA = REGISTER: 10
|
|
// sB = REGISTER: 11
|
|
// sC = REGISTER: 12
|
|
// sD = REGISTER: 13
|
|
// sE = REGISTER: 14
|
|
// sF = REGISTER: 15
|
|
// sample_count_lsb = CONSTANT: 32
|
|
// sample_count_msb = CONSTANT: 33
|
|
// set_dac = LABEL: 134
|
|
// sine_k_lsb = CONSTANT: 20
|
|
// sine_k_msb = CONSTANT: 21
|
|
// sine_y1_lsb = CONSTANT: 18
|
|
// sine_y1_msb = CONSTANT: 19
|
|
// sine_y_lsb = CONSTANT: 16
|
|
// sine_y_msb = CONSTANT: 17
|
|
// slope_down = LABEL: 42
|
|
// square_count = CONSTANT: 9
|
|
// square_high = LABEL: 58
|
|
// store_channel_B = LABEL: 50
|
|
// store_channel_C = LABEL: 60
|
|
// switch0 = CONSTANT: 16
|
|
// switch1 = CONSTANT: 32
|
|
// switch2 = CONSTANT: 64
|
|
// switch3 = CONSTANT: 128
|
|
// switch_port = CONSTANT: 0
|
|
// triangle_up_down = CONSTANT: 8
|
|
// wait_1ms = LABEL: 178
|
|
// wait_1s = LABEL: 188
|
|
// wait_1us = LABEL: 169
|
|
// wait_20ms = LABEL: 183
|
|
// wait_40us = LABEL: 173
|
|
// wait_int = LABEL: 16
|
|
// warm_start = LABEL: 15
|
|
|
|
/* Program Code */
|
|
// #1: ;KCPSM3 Program - SPI Control of D/A converter on Spartan-3E Starter Kit.
|
|
// #2: ;
|
|
// #3: ;
|
|
// #4: ;Ken Chapman - Xilinx Ltd
|
|
// #5: ;
|
|
// #6: ;Version v1.00 - 24th November 2005
|
|
// #7: ;
|
|
// #8: ;This program uses an 8KHz interrupt to generate test waveforms on the
|
|
// #9: ;4 analogue outputs provided by the Linear Technology LTC2624 device.
|
|
// #10: ;
|
|
// #11: ;As well as the port connections vital to communication with the UART and the SPI
|
|
// #12: ;FLASH memory, there are additional port connections used to disable the other
|
|
// #13: ;devices sharing the SPI bus on the Starter Kit board. Although these could have been
|
|
// #14: ;controlled at the hardware level, they are included in this code to aid
|
|
// #15: ;future investigations of communication with the other SPI devices using PicoBlaze.
|
|
// #16: ;
|
|
// #17: ;Connections to the LEDs, switches and press buttons are provided to aid
|
|
// #18: ;development and enable further experiments. Otherwise know as having fun!
|
|
// #19: ;
|
|
// #20: ;Port definitions
|
|
// #21: ;
|
|
// #22: ;
|
|
// #23: CONSTANT(SPI_control_port,8) ;SPI clock and chip selects
|
|
// #24: CONSTANT(SPI_sck,1) ; SCK - bit0
|
|
// #25: CONSTANT(SPI_rom_cs,2) ; serial rom select - bit1
|
|
// #26: CONSTANT(SPI_spare_control,4) ; spare - bit2
|
|
// #27: CONSTANT(SPI_amp_cs,8) ; amplifier select - bit3
|
|
// #28: CONSTANT(SPI_adc_conv,16) ; A/D convert - bit4
|
|
// #29: CONSTANT(SPI_dac_cs,32) ; D/A select - bit5
|
|
// #30: CONSTANT(SPI_amp_shdn,64) ; amplifier SHDN - bit6
|
|
// #31: CONSTANT(SPI_dac_clr,128) ; D/A clear - bit7
|
|
// #32: ;
|
|
// #33: CONSTANT(SPI_output_port,4) ;SPI data output
|
|
// #34: CONSTANT(SPI_sdo,128) ; SDO - bit7
|
|
// #35: ;
|
|
// #36: CONSTANT(SPI_input_port,1) ;SPI data input
|
|
// #37: CONSTANT(SPI_sdi,128) ; SDI - bit7
|
|
// #38: CONSTANT(SPI_amp_sdi,64) ; amplifier SDI - bit6
|
|
// #39: ;
|
|
// #40: ;
|
|
// #41: CONSTANT(LED_port,128) ;8 simple LEDs
|
|
// #42: CONSTANT(LED0,1) ; LED 0 - bit0
|
|
// #43: CONSTANT(LED1,2) ; 1 - bit1
|
|
// #44: CONSTANT(LED2,4) ; 2 - bit2
|
|
// #45: CONSTANT(LED3,8) ; 3 - bit3
|
|
// #46: CONSTANT(LED4,16) ; 4 - bit4
|
|
// #47: CONSTANT(LED5,32) ; 5 - bit5
|
|
// #48: CONSTANT(LED6,64) ; 6 - bit6
|
|
// #49: CONSTANT(LED7,128) ; 7 - bit7
|
|
// #50: ;
|
|
// #51: ;
|
|
// #52: CONSTANT(switch_port,0) ;Read switches and press buttons
|
|
// #53: CONSTANT(BTN_north,1) ; Buttons North - bit0
|
|
// #54: CONSTANT(BTN_east,2) ; East - bit1
|
|
// #55: CONSTANT(BTN_south,4) ; South - bit2
|
|
// #56: CONSTANT(BTN_west,8) ; West - bit3
|
|
// #57: CONSTANT(switch0,16) ; Switches 0 - bit4
|
|
// #58: CONSTANT(switch1,32) ; 1 - bit5
|
|
// #59: CONSTANT(switch2,64) ; 2 - bit6
|
|
// #60: CONSTANT(switch3,128) ; 3 - bit7
|
|
// #61: ;
|
|
// #62: ;
|
|
// #63: ;
|
|
// #64: ;
|
|
// #65: ;Special Register usage
|
|
// #66: ;
|
|
// #67: ;
|
|
// #68: ;Useful data constants
|
|
// #69: ;
|
|
// #70: ;
|
|
// #71: ;Constant to define a software delay of 1us. This must be adjusted to reflect the
|
|
// #72: ;clock applied to KCPSM3. Every instruction executes in 2 clock cycles making the
|
|
// #73: ;calculation highly predictable. The '6' in the following equation even allows for
|
|
// #74: ;'CALL delay_1us' instruction in the initiating code.
|
|
// #75: ;
|
|
// #76: ; delay_1us_constant = (clock_rate - 6)/4 Where 'clock_rate' is in MHz
|
|
// #77: ;
|
|
// #78: ;Example: For a 50MHz clock the constant value is (10-6)/4 = 11 (0B Hex).
|
|
// #79: ;For clock rates below 10MHz the value of 1 must be used and the operation will
|
|
// #80: ;become lower than intended.
|
|
// #81: ;
|
|
// #82: CONSTANT(delay_1us_constant,11)
|
|
// #83: ;
|
|
// #84: ;
|
|
// #85: ;
|
|
// #86: ;
|
|
// #87: ;
|
|
// #88: ;
|
|
// #89: ;Scratch Pad Memory Locations
|
|
// #90: ;
|
|
// #91: ;Values to be written to the D/A converter
|
|
// #92: ;
|
|
// #93: ;
|
|
// #94: CONSTANT(chan_A_lsb,0) ;Channel A value LS-Byte
|
|
// #95: CONSTANT(chan_A_msb,1) ; MS-Byte
|
|
// #96: ;
|
|
// #97: CONSTANT(chan_B_lsb,2) ;Channel B value LS-Byte
|
|
// #98: CONSTANT(chan_B_msb,3) ; MS-Byte
|
|
// #99: ;
|
|
// #100: CONSTANT(chan_C_lsb,4) ;Channel C value LS-Byte
|
|
// #101: CONSTANT(chan_C_msb,5) ; MS-Byte
|
|
// #102: ;
|
|
// #103: CONSTANT(chan_D_lsb,6) ;Channel D value LS-Byte
|
|
// #104: CONSTANT(chan_D_msb,7) ; MS-Byte
|
|
// #105: ;
|
|
// #106: ;
|
|
// #107: ;Value used to synthesise a triangle wave
|
|
// #108: ;
|
|
// #109: CONSTANT(triangle_up_down,8) ;Determines up or down slope
|
|
// #110: ;
|
|
// #111: ;Value used to synthesise a square wave
|
|
// #112: ;
|
|
// #113: CONSTANT(square_count,9) ;Counts samples in square wave
|
|
// #114: ;
|
|
// #115: ;
|
|
// #116: ;Values used to synthesise a sine wave
|
|
// #117: ;
|
|
// #118: CONSTANT(sine_y_lsb,16) ;Sine wave value LS-Byte
|
|
// #119: CONSTANT(sine_y_msb,17) ; MS-Byte
|
|
// #120: CONSTANT(sine_y1_lsb,18) ;Sine wave delayed LS-Byte
|
|
// #121: CONSTANT(sine_y1_msb,19) ; MS-Byte
|
|
// #122: CONSTANT(sine_k_lsb,20) ;Sine constant LS-Byte
|
|
// #123: CONSTANT(sine_k_msb,21) ; MS-Byte
|
|
// #124: ;
|
|
// #125: ;
|
|
// #126: ;Sample counter used to give activity indication on LEDs
|
|
// #127: ;
|
|
// #128: CONSTANT(sample_count_lsb,32) ;16-bit counter LS-Byte
|
|
// #129: CONSTANT(sample_count_msb,33) ; MS-Byte
|
|
// #130: ;
|
|
// #131: ;Initialise the system
|
|
// #132: ;
|
|
// #133: ;
|
|
// @000 #134: [cold_start]
|
|
30077 // @000 #134: CALL(SPI_init) ;initialise SPI bus ports
|
|
30052 // @001 #135: CALL(init_sine_wave) ;initialise sine wave synthesis values
|
|
300bb // @002 #136: CALL(delay_1s) ;bus settling delay
|
|
00000 // @003 #137: LOAD(s0,0) ;clear all internal D/A values
|
|
2e000 // @004 #138: STORE(s0,chan_A_lsb)
|
|
2e001 // @005 #139: STORE(s0,chan_A_msb)
|
|
2e002 // @006 #140: STORE(s0,chan_B_lsb)
|
|
2e003 // @007 #141: STORE(s0,chan_B_msb)
|
|
2e004 // @008 #142: STORE(s0,chan_C_lsb)
|
|
2e005 // @009 #143: STORE(s0,chan_C_msb)
|
|
2e006 // @00a #144: STORE(s0,chan_D_lsb)
|
|
2e007 // @00b #145: STORE(s0,chan_D_msb)
|
|
2e008 // @00c #146: STORE(s0,triangle_up_down) ;initial slope is up
|
|
300a2 // @00d #147: CALL(dac_reset) ;reset D/A converter on all channels
|
|
3c001 // @00e #148: ENABLE(INTERRUPT) ;Interrupts define 8KHz sample rate
|
|
// #149: ;
|
|
// #150: ;
|
|
// #151: ;The program is interrupt driven to maintain an 8KHz sample rate. The main body
|
|
// #152: ;of the program waits for an interrupt to occur. The interrupt updates all four
|
|
// #153: ;analogue outputs with values stored in scratch pad memory. This takes approximately
|
|
// #154: ;58us of the 125us available between interrupts. The main program then prepares
|
|
// #155: ;new values for the analogue outputs (in less than 67us) before waiting for the
|
|
// #156: ;next interrupt.
|
|
// #157: ;
|
|
// #158: ;
|
|
// @00f #159: [warm_start]
|
|
00fff // @00f #159: LOAD(sF,FF) ;flag set and wait for interrupt to be serviced
|
|
// @010 #160: [wait_int]
|
|
14fff // @010 #160: COMPARE(sF,FF)
|
|
35010 // @011 #161: JUMP(Z,wait_int) ;interrupt clears the flag
|
|
// #162: ;
|
|
// #163: ;
|
|
// #164: ;Channel A is a square wave of 2KHz.
|
|
// #165: ;
|
|
// #166: ;This is formed from the 2KHz square wave on channel C and demonstrates that the
|
|
// #167: ;D/A converter echoes the previously sent 32-bit command word.
|
|
// #168: ;
|
|
// #169: ;Following the interrupt service routine (ISR), the register set [s9,s8,s7,s6]
|
|
// #170: ;will contain the command which was last sent for the setting of channel C. The
|
|
// #171: ;12-bit sample value is extracted from this word and stored in the location for
|
|
// #172: ;channel A. This should mean that channel A is one sample behind channel C. In this
|
|
// #173: ;version that does not mean a lag of 90 degrees because each output is updated
|
|
// #174: ;sequentially and that takes approximatly 14.5us per channel.
|
|
// #175: ;
|
|
// #176: ;This will also demonstrate that the reference voltage on channels A and B is 3.3v
|
|
// #177: ;compared with 2.5v on channels C and D. So whilst the square wave on channel C is
|
|
// #178: ;set for 0.50v to 2.00v, it should be 0.66v to 2.64v on channel A.
|
|
// #179: ;
|
|
2070e // @012 #180: SR0(s7) ; shift 12-bit value right 4 places
|
|
20608 // @013 #181: SRA(s6)
|
|
2070e // @014 #182: SR0(s7)
|
|
20608 // @015 #183: SRA(s6)
|
|
2070e // @016 #184: SR0(s7)
|
|
20608 // @017 #185: SRA(s6)
|
|
2070e // @018 #186: SR0(s7)
|
|
20608 // @019 #187: SRA(s6)
|
|
2e701 // @01a #188: STORE(s7,chan_A_msb) ;store value for D/A output
|
|
2e600 // @01b #189: STORE(s6,chan_A_lsb)
|
|
// #190: ;
|
|
// #191: ;
|
|
// #192: ;
|
|
// #193: ;
|
|
// #194: ;Channel B is a triangle waveform of 200Hz.
|
|
// #195: ;
|
|
// #196: ;Given the sample rate of 8KHz, there are 40 samples per waveform period.
|
|
// #197: ;To achieve close to full scale deflection, the waveform needs to increase or
|
|
// #198: ;decrease by 204 each sample so that over the first 20 samples it rises from
|
|
// #199: ;0 to 4080 and then over the next 20 samples it reduces back to zero.
|
|
// #200: ;
|
|
06002 // @01c #201: FETCH(s0,chan_B_lsb) ;load current value into [s1,s0]
|
|
06103 // @01d #202: FETCH(s1,chan_B_msb)
|
|
06208 // @01e #203: FETCH(s2,triangle_up_down) ;read current slope direction
|
|
14200 // @01f #204: COMPARE(s2,0) ;determine current direction
|
|
3542a // @020 #205: JUMP(NZ,slope_down)
|
|
180cc // @021 #206: ADD(s0,CC) ;add 204 (00CC hex) to current value
|
|
1a100 // @022 #207: ADDCY(s1,0)
|
|
1410f // @023 #208: COMPARE(s1,15) ;test for peak value of 4080 (0FF0 hex)
|
|
35432 // @024 #209: JUMP(NZ,store_channel_B)
|
|
140f0 // @025 #210: COMPARE(s0,F0)
|
|
35432 // @026 #211: JUMP(NZ,store_channel_B)
|
|
00201 // @027 #212: LOAD(s2,1) ;change to slope down next time
|
|
2e208 // @028 #213: STORE(s2,triangle_up_down)
|
|
34032 // @029 #214: JUMP(store_channel_B)
|
|
// @02a #215: [slope_down]
|
|
1c0cc // @02a #215: SUB(s0,CC) ;subtract 204 (00CC hex) from current value
|
|
1e100 // @02b #216: SUBCY(s1,0)
|
|
14100 // @02c #217: COMPARE(s1,0) ;test for zero (0000 hex)
|
|
35432 // @02d #218: JUMP(NZ,store_channel_B)
|
|
14000 // @02e #219: COMPARE(s0,0)
|
|
35432 // @02f #220: JUMP(NZ,store_channel_B)
|
|
00200 // @030 #221: LOAD(s2,0) ;change to slope up next time
|
|
2e208 // @031 #222: STORE(s2,triangle_up_down)
|
|
// @032 #223: [store_channel_B]
|
|
2e002 // @032 #223: STORE(s0,chan_B_lsb) ;store value for D/A output
|
|
2e103 // @033 #224: STORE(s1,chan_B_msb)
|
|
// #225: ;
|
|
// #226: ;
|
|
// #227: ;Channel C is a square wave of 2KHz.
|
|
// #228: ;
|
|
// #229: ;Since the sample rate is 8KHz, this square wave is formed of two samples at a
|
|
// #230: ;low level and two samples at a high level. This is used to demonstrate when the
|
|
// #231: ;D/A converter output actually changes and how to determine the voltage levels.
|
|
// #232: ;It is also used indirectly to form the signal for channel A.
|
|
// #233: ;
|
|
// #234: ;The low level voltage is 0.50v.
|
|
// #235: ; The 12-bit value is therefore 4096 x 0.5 / 2.5 = 819 (333 hex)
|
|
// #236: ;
|
|
// #237: ;The high level voltage is 2.00v.
|
|
// #238: ; The 12-bit value is therefore 4096 x 2.0 / 2.5 = 3277 (CCD hex)
|
|
// #239: ;
|
|
// #240: ;
|
|
06209 // @034 #241: FETCH(s2,square_count) ;read sample counter
|
|
12202 // @035 #242: TEST(s2,2) ;bit 1 has correct frequency
|
|
3543a // @036 #243: JUMP(NZ,square_high)
|
|
00103 // @037 #244: LOAD(s1,3) ;Set low level
|
|
00033 // @038 #245: LOAD(s0,51)
|
|
3403c // @039 #246: JUMP(store_channel_C)
|
|
// @03a #247: [square_high]
|
|
0010c // @03a #247: LOAD(s1,12) ;Set high level
|
|
000cd // @03b #248: LOAD(s0,CD)
|
|
// @03c #249: [store_channel_C]
|
|
2e004 // @03c #249: STORE(s0,chan_C_lsb) ;store value for D/A output
|
|
2e105 // @03d #250: STORE(s1,chan_C_msb)
|
|
18201 // @03e #251: ADD(s2,1) ;increment sampel count
|
|
2e209 // @03f #252: STORE(s2,square_count) ;store new sample count
|
|
// #253: ;
|
|
// #254: ;Sine wave for channel D
|
|
// #255: ;
|
|
// #256: ;A synthesis algorithm is used to generate a stable 770Hz sine wave
|
|
// #257: ;which is one of the 8 tines used in DTMF telephone dialing.
|
|
// #258: ;
|
|
3005e // @040 #259: CALL(calc_next_sine)
|
|
2090e // @041 #260: SR0(s9) ;reduce value to 12-bits
|
|
20808 // @042 #261: SRA(s8)
|
|
2090e // @043 #262: SR0(s9)
|
|
20808 // @044 #263: SRA(s8)
|
|
2090e // @045 #264: SR0(s9)
|
|
20808 // @046 #265: SRA(s8)
|
|
18908 // @047 #266: ADD(s9,8) ;Scale signed number to mid-rail of unsigned output
|
|
2e907 // @048 #267: STORE(s9,chan_D_msb) ;store value for D/A output
|
|
2e806 // @049 #268: STORE(s8,chan_D_lsb)
|
|
// #269: ;
|
|
// #270: ;
|
|
// #271: ;Drive LEDs with simple binary count of the samples to indicate
|
|
// #272: ;that the design is active.
|
|
// #273: ;
|
|
06020 // @04a #274: FETCH(s0,sample_count_lsb) ;read sample counter
|
|
06121 // @04b #275: FETCH(s1,sample_count_msb)
|
|
18001 // @04c #276: ADD(s0,1) ;increment counter
|
|
1a100 // @04d #277: ADDCY(s1,0)
|
|
2e020 // @04e #278: STORE(s0,sample_count_lsb) ;store new value
|
|
2e121 // @04f #279: STORE(s1,sample_count_msb)
|
|
2c180 // @050 #280: OUTPUT(s1,LED_port) ;upper bits are 31.25Hz and lower
|
|
// #281: ;
|
|
3400f // @051 #282: JUMP(warm_start) ;wait for next interrupt
|
|
// #283: ;
|
|
// #284: ;**************************************************************************************
|
|
// #285: ;Sine wave synthesis algorithm
|
|
// #286: ;**************************************************************************************
|
|
// #287: ;
|
|
// #288: ;This example is set to generate 770Hz at a sample rate of 8KHz. 770Hz is one of
|
|
// #289: ;the eight DTMF frequences. Please see design documentation for more details.
|
|
// #290: ;
|
|
// @052 #291: [init_sine_wave]
|
|
00024 // @052 #291: LOAD(s0,36) ;initial value 9216 (2400 hex)
|
|
2e011 // @053 #292: STORE(s0,sine_y_msb)
|
|
00000 // @054 #293: LOAD(s0,0)
|
|
2e010 // @055 #294: STORE(s0,sine_y_lsb)
|
|
00000 // @056 #295: LOAD(s0,0) ;initial delayed value 0 (0000 hex)
|
|
2e013 // @057 #296: STORE(s0,sine_y1_msb)
|
|
2e012 // @058 #297: STORE(s0,sine_y1_lsb)
|
|
000d2 // @059 #298: LOAD(s0,D2) ;Coefficient for 770Hz is UFIX_16_15 value 53913/32768 = 1.64529
|
|
2e015 // @05a #299: STORE(s0,sine_k_msb)
|
|
00099 // @05b #300: LOAD(s0,153)
|
|
2e014 // @05c #301: STORE(s0,sine_k_lsb)
|
|
2a000 // @05d #302: RETURN
|
|
// #303: ;
|
|
// #304: ;
|
|
// #305: ;Calculate a new output sample for a single tone.
|
|
// #306: ;
|
|
// #307: ;The tone sample is generated as a 16-bit signed integer.
|
|
// #308: ;The waveform is virtually full scale deflection for a 15-bit integer
|
|
// #309: ;such that the addition of two tones for DTMF will not exceed the 16-bits
|
|
// #310: ;provided by two registers.
|
|
// #311: ;
|
|
// #312: ;Obtain current values from wscratch pad memory
|
|
// #313: ;
|
|
// @05e #314: [calc_next_sine]
|
|
06f11 // @05e #314: FETCH(sF,sine_y_msb) ;[sF,sE] is Y
|
|
06e10 // @05f #315: FETCH(sE,sine_y_lsb)
|
|
06d13 // @060 #316: FETCH(sD,sine_y1_msb) ;[sD,sC] is Y1
|
|
06c12 // @061 #317: FETCH(sC,sine_y1_lsb)
|
|
06b15 // @062 #318: FETCH(sB,sine_k_msb) ;[sB,sA] is K
|
|
06a14 // @063 #319: FETCH(sA,sine_k_lsb)
|
|
// #320: ;
|
|
// #321: ;16-bit signed by 16-bit unsigned multiplication. [s9,s8]=[sB,sA]x[sF,sE]
|
|
// #322: ;
|
|
// #323: ;The unsigned number is of format UFIX_16_15 resulting
|
|
// #324: ;in a FIX_32_15 product. Since only the integer part of the
|
|
// #325: ;product is to be retained as a 16-bit value, their is no
|
|
// #326: ;shift of the result on the last cycle of the multiplication.
|
|
// #327: ;Execution requires a maximum of 145 instructions.
|
|
// #328: ;
|
|
00900 // @064 #329: LOAD(s9,0) ;clear temporary result registers [s9,s8]
|
|
00800 // @065 #330: LOAD(s8,0)
|
|
00010 // @066 #331: LOAD(s0,16) ;16 bit multiply
|
|
// @067 #332: [mult_loop]
|
|
2090a // @067 #332: SRX(s9) ;signed divide result by 2
|
|
20808 // @068 #333: SRA(s8)
|
|
20b0e // @069 #334: SR0(sB) ;shift coefficient
|
|
20a08 // @06a #335: SRA(sA)
|
|
35c6e // @06b #336: JUMP(NC,no_mult_add) ;test for active bit
|
|
198e0 // @06c #337: ADD(s8,sE) ;16-bit signed addition
|
|
1b9f0 // @06d #338: ADDCY(s9,sF)
|
|
// @06e #339: [no_mult_add]
|
|
1c001 // @06e #339: SUB(s0,1) ;test for 16 cycles
|
|
35467 // @06f #340: JUMP(NZ,mult_loop)
|
|
// #341: ;
|
|
// #342: ;Subtract of delayed sample
|
|
// #343: ;
|
|
1d8c0 // @070 #344: SUB(s8,sC) ;16-bit signed subtract
|
|
1f9d0 // @071 #345: SUBCY(s9,sD)
|
|
// #346: ;
|
|
// #347: ;Update scratch pad memory with new sample values
|
|
// #348: ;
|
|
2ef13 // @072 #349: STORE(sF,sine_y1_msb) ;delayed sample gets previous output
|
|
2ee12 // @073 #350: STORE(sE,sine_y1_lsb)
|
|
2e911 // @074 #351: STORE(s9,sine_y_msb) ;new current sample
|
|
2e810 // @075 #352: STORE(s8,sine_y_lsb)
|
|
2a000 // @076 #353: RETURN
|
|
// #354: ;
|
|
// #355: ;
|
|
// #356: ;**************************************************************************************
|
|
// #357: ;SPI communication routines for D/A Converter
|
|
// #358: ;**************************************************************************************
|
|
// #359: ;
|
|
// #360: ;These routines will work with two output ports and one input port which should be
|
|
// #361: ;defined as follows using CONSTANT directives.
|
|
// #362: ; (replace 'pp' with appropriate port address in each case)
|
|
// #363: ;In the list of CONSTANT directives, only the ones marked with a * are really required
|
|
// #364: ;for the D/A Converter system. The other directives are to control (disable) or
|
|
// #365: ;communicate with the other SPI components on the same SPI bus of the Spartan-3E Starter Kit.
|
|
// #366: ;
|
|
// #367: ;
|
|
// #368: ;
|
|
// #369: ;CONSTANT SPI_control_port, pp ;SPI clock and chip selects *
|
|
// #370: ;CONSTANT SPI_sck, 01 ; SCK - bit0 *
|
|
// #371: ;CONSTANT SPI_rom_cs, 02 ; serial rom select - bit1
|
|
// #372: ;CONSTANT SPI_spare_control, 04 ; spare - bit2
|
|
// #373: ;CONSTANT SPI_amp_cs, 08 ; amplifier select - bit3
|
|
// #374: ;CONSTANT SPI_adc_conv, 10 ; A/D convert - bit4
|
|
// #375: ;CONSTANT SPI_dac_cs, 20 ; D/A select - bit5 *
|
|
// #376: ;CONSTANT SPI_amp_shdn, 40 ; amplifier SHDN - bit6
|
|
// #377: ;CONSTANT SPI_dac_clr, 80 ; D/A clear - bit7 *
|
|
// #378: ;
|
|
// #379: ;CONSTANT SPI_output_port, pp ;SPI data output *
|
|
// #380: ;CONSTANT SPI_sdo, 80 ; SDO - bit7 *
|
|
// #381: ;
|
|
// #382: ;CONSTANT SPI_input_port, pp ;SPI data input *
|
|
// #383: ;CONSTANT SPI_sdi, 80 ; SDI - bit7 *
|
|
// #384: ;CONSTANT SPI_amp_sdi, 40 ; amplifier SDI - bit6
|
|
// #385: ;
|
|
// #386: ;
|
|
// #387: ;
|
|
// #388: ;
|
|
// #389: ;Initialise SPI bus
|
|
// #390: ;
|
|
// #391: ;This routine should be used to initialise the SPI bus.
|
|
// #392: ;The SCK clock is made low.
|
|
// #393: ;Device selections are made inactive as follows
|
|
// #394: ; SPI_sck = 0 Clock is Low (required)
|
|
// #395: ; SPI_rom_cs = 1 Deselect ROM
|
|
// #396: ; spare = 1 spare control bit
|
|
// #397: ; SPI_amp_cs = 1 Deselect amplifier
|
|
// #398: ; SPI_adc_conv = 0 A/D convert ready to apply positive pulse
|
|
// #399: ; SPI_dac_cs = 1 Deselect D/A
|
|
// #400: ; SPI_amp_shdn = 0 Amplifier active and available
|
|
// #401: ; SPI_dac_clr = 1 D/A clear off
|
|
// #402: ;
|
|
// @077 #403: [SPI_init]
|
|
000ae // @077 #403: LOAD(s0,AE) ;normally AE
|
|
2c008 // @078 #404: OUTPUT(s0,SPI_control_port)
|
|
2a000 // @079 #405: RETURN
|
|
// #406: ;
|
|
// #407: ;
|
|
// #408: ;
|
|
// #409: ;Send and receive one byte to and from the SPI D/A converter.
|
|
// #410: ;
|
|
// #411: ;The data supplied in register 's2' is transmitted to the SPI bus and
|
|
// #412: ;at the same time the received byte is used to replace the value in 's2'.
|
|
// #413: ;The SCK clock is generated by software and results in a communication rate of
|
|
// #414: ;2.5Mbit/s with a 50MHz clock.
|
|
// #415: ;
|
|
// #416: ;Note that you must have previously selected the required device on the bus
|
|
// #417: ;before attempting communication and you must subsequently deselect the device
|
|
// #418: ;when appropriate.
|
|
// #419: ;
|
|
// #420: ;Entry to this routine assumes that register s0 defines the state of the SPI
|
|
// #421: ;control signals including SCK which should be Low. The easiest way to achieve this is
|
|
// #422: ;to use the SPI_init routine before calling this one for the first time.
|
|
// #423: ;
|
|
// #424: ;As a 'master' the signal sequence is as follows..
|
|
// #425: ; Transmit data bit on SDO line
|
|
// #426: ; Drive SCK transition from low to high
|
|
// #427: ; Receive data bit from SDI line (D/A transmits on previous falling edge)
|
|
// #428: ; Drive SCK transition from high to low.
|
|
// #429: ;
|
|
// #430: ;Important note
|
|
// #431: ; The received data bit must be captured some time before SCK goes low.
|
|
// #432: ; However the combination of relatively slow clock to output time of the
|
|
// #433: ; LTC2624 combined with the low drive strength of its SDO output means that
|
|
// #434: ; the received bit needs maximum time to settle. Therefore this routine
|
|
// #435: ; schedules the read as late as it can.
|
|
// #436: ;
|
|
// @07a #437: [SPI_dac_tx_rx]
|
|
00108 // @07a #437: LOAD(s1,8) ;8-bits to transmit and receive
|
|
// @07b #438: [next_SPI_dac_bit]
|
|
2c204 // @07b #438: OUTPUT(s2,SPI_output_port) ;output data bit ready to be used on rising edge
|
|
0e001 // @07c #439: XOR(s0,SPI_sck) ;clock High (bit0)
|
|
2c008 // @07d #440: OUTPUT(s0,SPI_control_port) ;drive clock High
|
|
0e001 // @07e #441: XOR(s0,SPI_sck) ;prepare clock Low (bit0)
|
|
04301 // @07f #442: INPUT(s3,SPI_input_port) ;read input bit
|
|
12380 // @080 #443: TEST(s3,SPI_sdi) ;detect state of received bit
|
|
20200 // @081 #444: SLA(s2) ;shift new data into result and move to next transmit bit
|
|
2c008 // @082 #445: OUTPUT(s0,SPI_control_port) ;drive clock Low
|
|
1c101 // @083 #446: SUB(s1,1) ;count bits
|
|
3547b // @084 #447: JUMP(NZ,next_SPI_dac_bit) ;repeat until finished
|
|
2a000 // @085 #448: RETURN
|
|
// #449: ;
|
|
// #450: ;
|
|
// #451: ;
|
|
// #452: ;Set a voltage on one of the LTC2624 D/A converter outputs
|
|
// #453: ;
|
|
// #454: ;The D/A converter has 4 channels. Specify which channel is to be set using
|
|
// #455: ;register sC as follows....
|
|
// #456: ; sC Channel Nominal Voltage Range
|
|
// #457: ; 00 A 0 to 3.30v (or VREFAB)
|
|
// #458: ; 01 B 0 to 3.30v (or VREFAB)
|
|
// #459: ; 02 C 0 to 2.50v (or VREFCD)
|
|
// #460: ; 03 D 0 to 2.50v (or VREFCD)
|
|
// #461: ; 0F All channels various as above.
|
|
// #462: ;
|
|
// #463: ;The analogue level is a 12-bit value to be supplied in lower 12-bits of register
|
|
// #464: ;pair [sB,sA]. If this value is called 'k' and is in the range 0 to 4095 (000 to FFF)
|
|
// #465: ;then
|
|
// #466: ; Vout = (k/4096) * VREFx
|
|
// #467: ;Hence it is not possible to reach the absolute level of the reference.
|
|
// #468: ;
|
|
// #469: ;Here are some useful values..
|
|
// #470: ; Voltage A or B C or D
|
|
// #471: ; 0.0 000 000
|
|
// #472: ; 0.5 26D 333
|
|
// #473: ; 0.65 327 A/D reference -1.00v
|
|
// #474: ; 1.0 4D9 666
|
|
// #475: ; 1.5 746 99A
|
|
// #476: ; 1.65 800 A8F converter reference = 3.3/2 = 1.65v
|
|
// #477: ; 2.0 9B2 CCD
|
|
// #478: ; 2.5 C1F FFF
|
|
// #479: ; 2.65 CD9 A/D reference +1.00v
|
|
// #480: ; 3.0 E8C n/a
|
|
// #481: ; 3.3 FFF n/a
|
|
// #482: ;
|
|
// #483: ;Note that the full scale deflection of FFF will result in different output
|
|
// #484: ;voltages due to different reference voltages for each pair of channels.
|
|
// #485: ;
|
|
// #486: ;SPI communication with the DAC only requires a 24-bit word to be transmitted.
|
|
// #487: ;However, the device internally contains a 32-bit shift register. When writing
|
|
// #488: ;a command word, the previous contents are shifted out and can be observed by
|
|
// #489: ;the master (Spartan-3E in this case). If you do not use a 32-bit format, then
|
|
// #490: ;the read back is confusing. Hence this routine uses a 32-bit format by transmitting
|
|
// #491: ;a dummy byte first.
|
|
// #492: ;
|
|
// #493: ; Byte 1 = 00 8 dummy bits
|
|
// #494: ; Byte 2 = 3c Command nibble (3=write and update) and channel selection
|
|
// #495: ; Byte 3 = dd Upper 8-bits of the 12-bit voltage value
|
|
// #496: ; Byte 4 = d0 lower 4-bits of the 12-bit voltage value and 4 dummy bits.
|
|
// #497: ;
|
|
// #498: ;At the end of this communication, the register set [s9,s8,s7,s6] will contain the
|
|
// #499: ;data received back from the D/A converter which should be the previous command.
|
|
// #500: ;
|
|
// @086 #501: [set_dac]
|
|
30077 // @086 #501: CALL(SPI_init) ;ensure known state of bus and s0 register
|
|
0e020 // @087 #502: XOR(s0,SPI_dac_cs) ;select low on D/A converter
|
|
2c008 // @088 #503: OUTPUT(s0,SPI_control_port)
|
|
00200 // @089 #504: LOAD(s2,0) ;Write dummy byte to DAC
|
|
3007a // @08a #505: CALL(SPI_dac_tx_rx)
|
|
01920 // @08b #506: LOAD(s9,s2) ;capture response
|
|
012c0 // @08c #507: LOAD(s2,sC) ;Select channel for update
|
|
0a20f // @08d #508: AND(s2,15) ;isolate channel bits to be certain of correct command
|
|
0c230 // @08e #509: OR(s2,48) ;Use immediate Write and Update command is "0011"
|
|
3007a // @08f #510: CALL(SPI_dac_tx_rx)
|
|
01820 // @090 #511: LOAD(s8,s2) ;capture response
|
|
20a06 // @091 #512: SL0(sA) ;data shift bits into correct position
|
|
20b00 // @092 #513: SLA(sB) ;with 4 dummy bits ('0') in the least significant bits.
|
|
20a06 // @093 #514: SL0(sA)
|
|
20b00 // @094 #515: SLA(sB)
|
|
20a06 // @095 #516: SL0(sA)
|
|
20b00 // @096 #517: SLA(sB)
|
|
20a06 // @097 #518: SL0(sA)
|
|
20b00 // @098 #519: SLA(sB)
|
|
012b0 // @099 #520: LOAD(s2,sB) ;Write 12 bit value followed by 4 dummy bits
|
|
3007a // @09a #521: CALL(SPI_dac_tx_rx)
|
|
01720 // @09b #522: LOAD(s7,s2) ;capture response
|
|
012a0 // @09c #523: LOAD(s2,sA)
|
|
3007a // @09d #524: CALL(SPI_dac_tx_rx)
|
|
01620 // @09e #525: LOAD(s6,s2) ;capture response
|
|
0e020 // @09f #526: XOR(s0,SPI_dac_cs) ;deselect the D/A converter to execute
|
|
2c008 // @0a0 #527: OUTPUT(s0,SPI_control_port)
|
|
2a000 // @0a1 #528: RETURN
|
|
// #529: ;
|
|
// #530: ;Perform a hard reset of the D/A converter
|
|
// #531: ;
|
|
// @0a2 #532: [dac_reset]
|
|
30077 // @0a2 #532: CALL(SPI_init) ;ensure known state of bus and s0 register
|
|
0e080 // @0a3 #533: XOR(s0,SPI_dac_clr) ;pulse the clear signal.
|
|
2c008 // @0a4 #534: OUTPUT(s0,SPI_control_port)
|
|
0e080 // @0a5 #535: XOR(s0,SPI_dac_clr)
|
|
2c008 // @0a6 #536: OUTPUT(s0,SPI_control_port)
|
|
2a000 // @0a7 #537: RETURN
|
|
// #538: ;
|
|
// #539: ;
|
|
// #540: ;**************************************************************************************
|
|
// #541: ;Software delay routines
|
|
// #542: ;**************************************************************************************
|
|
// #543: ;
|
|
// #544: ;
|
|
// #545: ;
|
|
// #546: ;Delay of 1us.
|
|
// #547: ;
|
|
// #548: ;Constant value defines reflects the clock applied to KCPSM3. Every instruction
|
|
// #549: ;executes in 2 clock cycles making the calculation highly predictable. The '6' in
|
|
// #550: ;the following equation even allows for 'CALL delay_1us' instruction in the initiating code.
|
|
// #551: ;
|
|
// #552: ; delay_1us_constant = (clock_rate - 6)/4 Where 'clock_rate' is in MHz
|
|
// #553: ;
|
|
// #554: ;Registers used s0
|
|
// #555: ;
|
|
// @0a8 #556: [delay_1us]
|
|
0000b // @0a8 #556: LOAD(s0,delay_1us_constant)
|
|
// @0a9 #557: [wait_1us]
|
|
1c001 // @0a9 #557: SUB(s0,1)
|
|
354a9 // @0aa #558: JUMP(NZ,wait_1us)
|
|
2a000 // @0ab #559: RETURN
|
|
// #560: ;
|
|
// #561: ;Delay of 40us.
|
|
// #562: ;
|
|
// #563: ;Registers used s0, s1
|
|
// #564: ;
|
|
// @0ac #565: [delay_40us]
|
|
00128 // @0ac #565: LOAD(s1,40) ;40 x 1us = 40us
|
|
// @0ad #566: [wait_40us]
|
|
300a8 // @0ad #566: CALL(delay_1us)
|
|
1c101 // @0ae #567: SUB(s1,1)
|
|
354ad // @0af #568: JUMP(NZ,wait_40us)
|
|
2a000 // @0b0 #569: RETURN
|
|
// #570: ;
|
|
// #571: ;
|
|
// #572: ;Delay of 1ms.
|
|
// #573: ;
|
|
// #574: ;Registers used s0, s1, s2
|
|
// #575: ;
|
|
// @0b1 #576: [delay_1ms]
|
|
00219 // @0b1 #576: LOAD(s2,25) ;25 x 40us = 1ms
|
|
// @0b2 #577: [wait_1ms]
|
|
300ac // @0b2 #577: CALL(delay_40us)
|
|
1c201 // @0b3 #578: SUB(s2,1)
|
|
354b2 // @0b4 #579: JUMP(NZ,wait_1ms)
|
|
2a000 // @0b5 #580: RETURN
|
|
// #581: ;
|
|
// #582: ;Delay of 20ms.
|
|
// #583: ;
|
|
// #584: ;Delay of 20ms used during initialisation.
|
|
// #585: ;
|
|
// #586: ;Registers used s0, s1, s2, s3
|
|
// #587: ;
|
|
// @0b6 #588: [delay_20ms]
|
|
00314 // @0b6 #588: LOAD(s3,20) ;20 x 1ms = 20ms
|
|
// @0b7 #589: [wait_20ms]
|
|
300b1 // @0b7 #589: CALL(delay_1ms)
|
|
1c301 // @0b8 #590: SUB(s3,1)
|
|
354b7 // @0b9 #591: JUMP(NZ,wait_20ms)
|
|
2a000 // @0ba #592: RETURN
|
|
// #593: ;
|
|
// #594: ;Delay of approximately 1 second.
|
|
// #595: ;
|
|
// #596: ;Registers used s0, s1, s2, s3, s4
|
|
// #597: ;
|
|
// @0bb #598: [delay_1s]
|
|
00414 // @0bb #598: LOAD(s4,20) ;50 x 20ms = 1000ms
|
|
// @0bc #599: [wait_1s]
|
|
300b6 // @0bc #599: CALL(delay_20ms)
|
|
1c401 // @0bd #600: SUB(s4,1)
|
|
354bc // @0be #601: JUMP(NZ,wait_1s)
|
|
2a000 // @0bf #602: RETURN
|
|
// #603: ;
|
|
// #604: ;
|
|
// #605: ;
|
|
// #606: ;**************************************************************************************
|
|
// #607: ;Interrupt Service Routine (ISR)
|
|
// #608: ;**************************************************************************************
|
|
// #609: ;
|
|
// #610: ;Interrupts occur at a rate of 8KHz.
|
|
// #611: ;
|
|
// #612: ;Each interrupt is the fundamental timing trigger used to set the sample rate and
|
|
// #613: ;it is therefore use to set the D/A outputs by copying the values stored in
|
|
// #614: ;scratch pad memory and outputting them to the D/A converter using the SPI bus.
|
|
// #615: ;
|
|
// #616: ;Because the SPI communication is in itself a predictable process, the sample rate
|
|
// #617: ;is preserved without sample jitter. All variable activities are left to the main
|
|
// #618: ;program.
|
|
// #619: ;
|
|
// #620: ;Each time PicoBlaze transmits a 32-bit command word to the D/A converter, the
|
|
// #621: ;D/A responds with the last command it was sent. So as the end of this service routine
|
|
// #622: ;the register set [s9,s8,s7,s6] will contain the command which has just been sent
|
|
// #623: ;for the setting of channel C.
|
|
// #624: ;
|
|
// #625: ;Set channel A
|
|
// #626: ;
|
|
// @0c0 #627: [ISR]
|
|
00c00 // @0c0 #627: LOAD(sC,0) ;channel A
|
|
06b01 // @0c1 #628: FETCH(sB,chan_A_msb) ;12-bit value
|
|
06a00 // @0c2 #629: FETCH(sA,chan_A_lsb)
|
|
30086 // @0c3 #630: CALL(set_dac)
|
|
// #631: ;
|
|
// #632: ;Set channel B
|
|
// #633: ;
|
|
00c01 // @0c4 #634: LOAD(sC,1) ;channel B
|
|
06b03 // @0c5 #635: FETCH(sB,chan_B_msb) ;12-bit value
|
|
06a02 // @0c6 #636: FETCH(sA,chan_B_lsb)
|
|
30086 // @0c7 #637: CALL(set_dac)
|
|
// #638: ;
|
|
// #639: ;Set channel C
|
|
// #640: ;
|
|
00c02 // @0c8 #641: LOAD(sC,2) ;channel C
|
|
06b05 // @0c9 #642: FETCH(sB,chan_C_msb) ;12-bit value
|
|
06a04 // @0ca #643: FETCH(sA,chan_C_lsb)
|
|
30086 // @0cb #644: CALL(set_dac)
|
|
// #645: ;
|
|
// #646: ;Set channel A
|
|
// #647: ;
|
|
00c03 // @0cc #648: LOAD(sC,3) ;channel D
|
|
06b07 // @0cd #649: FETCH(sB,chan_D_msb) ;12-bit value
|
|
06a06 // @0ce #650: FETCH(sA,chan_D_lsb)
|
|
30086 // @0cf #651: CALL(set_dac)
|
|
// #652: ;
|
|
00f00 // @0d0 #653: LOAD(sF,0) ;clear flag
|
|
38001 // @0d1 #654: RETURNI(ENABLE)
|
|
// #655: ;
|
|
// #656: ;
|
|
// #657: ;**************************************************************************************
|
|
// #658: ;Interrupt Vector
|
|
// #659: ;**************************************************************************************
|
|
// #660: ;
|
|
@3ff // #661: ADDRESS(1023)
|
|
340c0 // @3ff #662: JUMP(ISR)
|
|
// #663: ;
|
|
// #664: ;
|