Locked[FAQ]SCL Code repository

Author
Guest
Super Member
  • Total Posts : 80499
  • Reward points : 0
  • Joined: 2003/01/01 00:00:00
  • Location: 0
  • Status: online
2005/08/22 11:06:35 (permalink)
0

SCL Code repository

Hi,
SCL is the Stimulus Control Language, adopted by Microchip as the foundation of external stimuli generation for MPSIM.
SCL looks like a dialect of VHDL (Very high-speed IC Hardware Description Language).
According to JasonK of Microchip, SCL is similar, but not a direct subset of VHDL.
Nevertheless, the syntax for SCL follows VHDL very closely;
This is a landmark in development with MPLAB IDE and will bring design verification to a new level.
Using SCL you can generate complex waveforms, emulate external hardware, simulate complex serial protocols, verify response of algorithms and detect errors, analyse system latency and real-time response to stimulus, and more.
As of now, SCL is an undocumented feature.
We are trying to convey information that the forum community may have using the SCL as an effort to know the boundaries of this powerful tool.


This thread is meant to be a repository of tested and working SCL files and SCL code techniques that you want to share with others.
Please do not post SCL doubts and request for support on SCL here, post it as a new thread in MPLAB Simulator forum.
If you want to partake in the SCL research effort there is another thread we are devoting to SCL research, called Coding directly in SCL\SCL as VHDL subset.
A SCL Tutorial is being run at the thread SCL PRIMER / TUTORIAL for those who want to learn the undocumented SCL language.

When posting SCL code snippets here, please follow commonsense rules of documenting any non-obvious feature in your code, and include your code between [code] [/code] tags.
Always reply to the last post, not the first. This way I can add it to an index with all the entries.

I hope this can help people to get used to the SCL, and ultimately drive Microchip to document it and enhance its capabilities.


CODE REPOSITORY INDEX

- TIMER1 OSC with extenal 32.768KHz crystal
- ADC STIMULUS FROM A TEXT DATAFILE FOR PIC16F SERIES
- Input to a Simulation From an External Application
- MANCHESTER ENCODER OF BINARY VALUES READ FROM A FILE
- ADC STIMULUS FROM A TEXT DATAFILE FOR PIC18F SERIES
- ADC STIMULUS FOR PIC18F SERIES (FAST VERSION)
- TIMER1 OSC with external 32.768KHz for the PIC16F914
post edited by KajitaJ2 - 2006/01/31 09:53:45
#1

10 Replies Related Threads

    Guest
    Super Member
    • Total Posts : 80499
    • Reward points : 0
    • Joined: 2003/01/01 00:00:00
    • Location: 0
    • Status: online
    RE: SCL/VHDL Code repository 2005/08/22 11:08:57 (permalink)
    0
    TIMER1 OSC with extenal 32.768KHz crystal

    // test_OSC32K_8MHz.scl
    // Hand-Generated by j_doin
    //
    // This testbench has a process _TMR1OSC that generates
    // an accurate realistic 32768Hz clock into pin CLKIN of
    // a PIC16F688 to be used as external clock or TIMER1OSC.
    // Any TIMER1 oscillator PIC can be simulated with this.
    //
    // The timings are independent from device MPSIM frequency,
    // but there are versions hand-tumed for each clock frequency,
    // due to the minimum TCycle resolution.

    configuration for "pic16f688" is
    end configuration;

    testbench for "pic16f688" is
    begin

    _TMR1OSC: process is
    // This emulates the TMR1OSC by feeding input to the pin
    // RA5/CLKIN.
    // OSC1 freq = 32767.83616Hz, for a clock of 8MHz.
    // The generator has a pattern of 99 cycles.
    // No clock startup time is simulated.
    variable iter : integer;
    begin
    RA5 <= '0'; // value at power-on
    loop
    iter := 1;
    while iter <= 56 loop
    wait for 15.0 us;
    RA5 <= not RA5;
    wait for 16.0 us;
    RA5 <= not RA5;
    iter := iter + 1;
    end loop;
    iter := 1;
    while iter <= 107 loop
    wait for 15.0 us;
    RA5 <= not RA5;
    iter := iter + 1;
    end loop;
    end loop;
    wait;
    end process;

    end testbench;
    < Message edited by j_doin -- Aug. 26, 2005 1:05:22 PM >
    #2
    Guest
    Super Member
    • Total Posts : 80499
    • Reward points : 0
    • Joined: 2003/01/01 00:00:00
    • Location: 0
    • Status: online
    RE: SCL/VHDL Code repository 2005/08/25 11:35:45 (permalink)
    0
    Updated for MPLAB version 7.21
    In MPLAB 7.21 you can change the SFRs that are being driven by the simulator engine! The restriction on ADCON0.ADON is lifted.


    A2D CONVERTER WITH WAVEFORM GENERATION FROM DATAFILE
    The following testbench reads datapoints from a file, generates a periodic waveform and feeds the data points into the A/D converter. It emulates the A/D converter and starts a conversion when bit ADCON0.GO is set, raising bit PIR1.ADIF and updating registers ADRESH and ADRESL according to the justification specs.

    Currently this style of stimulus is NOT WORKING for dsPIC30F60xx or PIC18Fxxx devices. See other posts for PIC18F compatible ADC injection.

    Important: Copy/paste the example waveform definition file to a file named "datapoints.txt" before starting the simulation, or MPSIM will hang.

    // Wavefile.scl
    // Hand-Generated by j_doin, 2005/09/24
    //
    // This testbench has a process WAVEFORM that reads
    // data points from a text file and continuously generate
    // a stream of discrete datapoints.
    // This discrete waveform is sampled by the A2D_CONVERTER
    // process, when bit ADCON0.GO_nDONE is set to '1'
    //

    configuration for "pic16f688" is
    end configuration;

    testbench for "pic16f688" is
    begin

    WAVEFORM: process is
    // read a raw data file of points, and continuously scans from the
    // start to end of the file.
    file data_file : text;
    variable status : file_open_status;
    variable data_line: line;
    variable data_point : integer;
    variable sample_time : time;
    variable filler : integer;
    begin
    sample_time := 10 us; // default sample time
    wait until ADCON0.GO_nDONE == '1'; // sync waveform to A2D start
    loop
    file_open(status, data_file, "datapoints.txt", read_mode);
    if status == open_ok then
    while endfile(data_file) == false loop
    readline(data_file, data_line);
    if match(data_line, "") == true then // skip empty line
    elsif match(data_line, "//") == true then // skip comments
    elsif match(data_line, "time") == true then // process cmd "time"
    read(data_line, filler); // discard string "time"
    read(data_line, sample_time); // read sample time
    elsif match(data_line, "hold") == true then // cmd "hold"
    wait for sample_time; // hold line for 1 sample time
    else
    while match(data_line, "") == false loop
    if match(data_line, "//") == true then // skip end line comments
    exit; // skip to next line
    else
    wait for sample_time; // sample time delay
    read(data_line, data_point); // get data point
    end if;
    end loop;
    end if;
    end loop;
    file_close(data_file); // end-of-file: close to reopen.
    end if;
    end loop;
    wait;
    end process;

    A2D_CONVERTER: process is
    variable conv_time : time;
    begin
    // init the ADCONV operating constants
    conv_time := 19 us; // set to conversion time (12Tad)
    ADRESH <= 0; // value at power-on
    ADRESL <= 0;
    loop
    wait until ADCON0.GO_nDONE == '1';
    if ADCON0.ADON == '1' then // simulate A2D only if AD is ON
    wait for conv_time;
    if ADCON0.ADFM == '0' then // process right/left justification
    ADRESH <= data_point / 4;
    ADRESL <= data_point * 64; // MPSIM will clip to 16#FF#
    else
    ADRESH <= data_point / 256;
    ADRESL <= data_point; // MPSIM will clip to 16#FF#
    end if;
    ADCON0.GO_nDONE <= '0';
    PIR1.ADIF <= '1';
    end if;
    end loop;
    wait;
    end process;

    end testbench;


    The WAVEFORM process reads all datapoints and starts over, generating a periodic discrete waveform.
    A sample textfile for the datapoints is as follows (cut/paste in a file named "datapoints.txt") :


    time 1 ms // start at 0000, 1KSPS
    // Long lines are possible:
    0 1 2 3 4 5 6 7 8
    9 10 11 12 13 14 15
    // next line is ignored

    time 100 us // the next section is at 10KSPS
    100 110 115 110 100
    100 90 85 90 100
    time 9ms // long pause of 10ms
    hold // this holds the line at current value
    time 1ms // resume to 1KSPS
    1000
    1010
    1023


    The SCL file is attached here, with tab indenting instead of spaces (remove the ".txt" from the filename):
    < Message edited by j_doin -- Sep. 10, 2005 10:32:48 PM >
    #3
    russeld
    Starting Member
    • Total Posts : 50
    • Reward points : 0
    • Joined: 2003/11/07 12:43:31
    • Status: offline
    RE: SCL/VHDL Code repository 2005/08/29 08:20:31 (permalink)
    0
    Input to a Simulation From an External Application

    Control a simulation using a VBA applet with a keypad and a slider to set the A-D value:

    The simulation was written for the 16F88. Ensure that the correct device is selected in MPLAB else the SCL file will not attach.
    Aternativly change the device in the SCL file.

    NOTE: The attachment gets zapped after 30 days. If you pm me I will re-attach it.






    -- Hand coded russeld -- 28 August 2005 -- Tested MPLAB V7.20
    -- The purpose of this testbench is to illustrate the use of an external
    -- control with an SCL simulation.
    --
    -- The external control has a 4 x 4 keypad and a slider to simulate the voltage
    -- input to the A-D.
    --
    -- The SCL testbench reads two files generated by the app: "A-D value.txt"
    -- and "key value.txt" and updates ADRES and PORTB accordingly.
    -- The testbench is constructed to simulate the keypad row lines connected to
    -- RB0 to RB3 and the column lines to RB4 to RB7, with pullup resistors on the
    -- column lines. No contact bounce is simulated - though this could be added -
    -- To run the simulation:
    --      Create a project and add the attached file "SCL Ext Ctrl.asm".
    --      Copy the attached spreadsheet "SCL Ext Ctrl.xls" to the project
    --      directory.
    --      Add two watches - AD_Res16 and KeyCode. Set AD_Res16 to 16 bit, decimal.
    --      To be able to view the effect of the control on the simulation, while the
    --          simulation is running at full speed, ensure that "Enable realtime watch updates"
    --          is checked on the "Animate/Realtime Update" tab of the Debugger Settings
    --      dialog. Set the update rate to 1 x 100ms.
    --      Copy and paste this testbench into an SCL file and attach it using the
    --          Stimulus Controller.
    --      Open the spreadsheet. Click 'Enable Macros' (at your own risk). This
    --          should hide Excel and open the VB app.
    --      In MPLAB Run the simulation (F9) and view the effect of moving the slider and pressing
    --         the keys on the external control. the KeyCode variable should reflect the key being
    --         pressed and 0xFF when no keys are pressed. AD_Res16 should vary between 0 to 1023 for
    --         a 0 to 5V input on the slider.
    --
    --  Why VB and Excel? - simply because most people have access to Excel and can
    --  change the code and experiment further themselves.
    --
    --  To view the VB code, disable macros when prompted by Excel and follow the
    --  instructions in the spreadsheet. The code is by no means optimal - I am no
    --  VB expert and personally prefer Delphi and C-Builder.
    configuration for "pic16f88" is
    end configuration;
    testbench for "pic16f88" is
    begin
        GET_AD: process is
        begin
            accessin("A-D value.txt", dec_mode, ADRESL, true);
            wait for 10 us;
        end process;
        GET_KEY: process is
            file keydat : text;
            variable file_status : file_open_status;
            variable col, row, dummy : integer;
            variable L : line;
            variable S4, S5, S6, S7 : bit; -- Manipulate S4 .. S7 - Update RB4 to RB7 at end of process.
        begin        
            file_open(file_status, keydat, "key_value.txt", read_mode);
            if file_status == open_ok then
                readline(keydat, L);
                read(L, row);
                readline(keydat, L);
                read(L, col);
                file_close(keydat);
                S4 := '1';
                S5 := '1';
                S6 := '1';
                S7 := '1';
               
            -- The following can be simplified if compound 'if' statements or 'case' statements ever get implemented
                if row /= 15 then
                    if col /= 15 then
                       
                        if col > 3 then -- check for out of bound data
                            report "Col data invalid";
                        end if;
                        if row > 3 then
                            report "Row data invalid";
                        end if;
                        if row == 0 then 
                            if col == 0 then
                                S4 := RB0;
                            elsif col == 1 then
                                S5 := RB0;
                            elsif col == 2 then
                                S6 := RB0;
                            else
                                S7 := RB0;
                            end if;
                        elsif row == 1 then
                            if col == 0 then
                                S4 := RB1;
                            elsif col == 1 then
                                S5 := RB1;
                            elsif col == 2 then
                                S6 := RB1;
                            else
                                S7 := RB1;
                            end if;
                        elsif row == 2 then
                            if col == 0 then
                                S4 := RB2;
                            elsif col == 1 then
                                S5 := RB2;
                            elsif col == 2 then
                                S6 := RB2;
                            else
                                S7 := RB2;
                            end if;
                        elsif row == 3 then
                            if col == 0 then
                                S4 := RB3;
                            elsif col == 1 then
                                S5 := RB3;
                            elsif col == 2 then
                                S6 := RB3;
                            else
                                S7 := RB3;
                            end if;
                        end if;
                    end if;
                end if;
                RB4 <= S4;
                RB5 <= S5;
                RB6 <= S6;
                RB7 <= S7;
            end if;
            wait for 1 ic;
        end process;
    end testbench;


    The VBA app (in Excel), SCL file and assembler source file are included in the attached zip file
    post edited by russeld - 2009/06/09 00:55:12
    #4
    Guest
    Super Member
    • Total Posts : 80499
    • Reward points : 0
    • Joined: 2003/01/01 00:00:00
    • Location: 0
    • Status: online
    RE: SCL/VHDL Code repository 2005/08/31 05:19:33 (permalink)
    0
    MANCHESTER ENCODER OF BINARY VALUES READ FROM A FILE

    Important: create a text file named "manchester.txt" with the contents cut/paste from the example data file at the bottom of this message, prior to start the MPSIM simulation, or the simulator will hang.

    Currently this style of stimulus is NOT WORKING for dsPIC30F60xx or PIC18Fxxx devices.



    -- MANCHESTER.scl
    -- Hand-Generated by j_doin, 2005/09/30
    --
    -- This testbench has a process MANCHESTER that reads
    -- binary codes from a file and injects manchester-encoded
    -- signals into a user pin.
    -- The binary codes are encoded as binary values ("0" or "1") separated by a space,
    -- Commands for symbol time, wait time, and stop are recognized
    --

    configuration for "pic16f688" is
    end configuration;

    testbench for "pic16f688" is
    begin

    MANCHESTER: process is
    -- read a binary codes file and inject Mancester Encoded data
    -- to a user pin.
    -- TO CHANGE THE INPUT PIN, EDIT ALL "RC0" OCCURRENCES AND CHANGE TO YOUR PIN
    file data_file : text;
    variable status : file_open_status;
    variable data_line: line;
    variable data_point : integer;
    variable symbol_time : time;
    variable wait_time : time;
    variable exitloop : boolean;
    variable filler : integer;
    begin
    -- default symbol time value
    symbol_time := 416 us; -- default symbol time: 416 µs
    exitloop := false;
    while exitloop == false loop
    file_open(status, data_file, "manchester.txt", read_mode);
    if status == open_ok then
    if exitloop == false then
    while endfile(data_file) == false loop
    readline(data_file, data_line);
    if match(data_line, "") == true then -- skip empty line
    elsif match(data_line, "--") == true then -- skip comments
    elsif match(data_line, "symtime") == true then -- process cmd "symtime"
    read(data_line, filler); -- discard string "symtime"
    read(data_line, symbol_time); -- read symbol time
    elsif match(data_line, "wait") == true then -- process cmd "wait"
    read(data_line, filler); -- discard string "wait"
    read(data_line, wait_time); -- read symbol time
    wait for wait_time;
    elsif match(data_line, "stop") == true then -- process cmd "stop"
    exitloop := true;
    exit;
    elsif match(data_line, "sync") == true then -- process cmd "sync"
    //Data 1
    RC0 <= '1';
    wait for symbol_time;
    RC0 <= '0';
    wait for symbol_time;
    //Sync Header
    wait for symbol_time;
    wait for symbol_time;
    wait for symbol_time;
    wait for symbol_time;
    else
    while match(data_line, "") == false loop
    if match(data_line, "--") == true then -- skip end line comments
    exit; -- skip to next line
    else
    if match(data_line, "0") == true then
    -- encode a "0"
    read(data_line, data_point); -- get data point
    RC0 <= '0';
    wait for symbol_time;
    RC0 <= '1';
    wait for symbol_time;
    elsif match(data_line, "1") == true then
    -- encode a "1"
    read(data_line, data_point); -- get data point
    RC0 <= '1';
    wait for symbol_time;
    RC0 <= '0';
    wait for symbol_time;
    else
    read(data_line, filler); -- consume nonsignificant datum
    end if;
    end if;
    end loop;
    end if;
    end loop;
    end if;
    file_close(data_file); -- end-of-file: close to reopen.
    end if;
    end loop;
    wait;
    end process MANCHESTER;

    end testbench;



    The vector text file is like this (cut/paste in a file named "manchester.txt"):


    // Manchester encoder data file
    // place bit binary values in each line, separated by spaces.
    // The bit stream can be as long as you want.
    // Continuing the bit stream in the next line is the same as putting it in the same line.
    // a "wait" command introduces a pause in time units
    // the command "symtime" changes the symbol time.
    // If no "symtime" is specified, it defaults to 416 us.
    // a "sync" command sends the sync sequence( a '1' followed by 4 symbol times)
    // if the command "stop" is found, the data generation stops.
    // if no "stop" command is found, the file will restart from the beginning.
    symtime 500 us
    wait 2000 us
    sync
    1 0 1 0 1 0 1 1
    stop // stop: make a one-pass only


    The SCL file is attached here, with indenting tabs instead of spaces (remove the .txt from the filename):
    < Message edited by j_doin -- Sep. 10, 2005 10:33:16 PM >
    #5
    Guest
    Super Member
    • Total Posts : 80499
    • Reward points : 0
    • Joined: 2003/01/01 00:00:00
    • Location: 0
    • Status: online
    RE: SCL/VHDL Code repository 2005/09/10 18:31:05 (permalink)
    0
    ADC INJECTION FROM A TEXTFILE - FOR PIC18F SERIES - (COMPLETE VERSION)

    The following code is a model of the ADC of PIC18F devices. It accurately detects internal MPSIM simulation of the ADC and stuffs the ADRES registers with values read from a file, according to justification mode.
    It detects ADC config errors and sampling/conversion time violations.

    Important: Create a text file called "datapoints.txt" with the contents cut/paste from the example data file at the bottom of this message, prior to start the MPSIM simulation, or the simulator will hang.

    The simulator will print a warning message: "ADC-W0008: No stimulus file attached to ADRESL for A/D" when the ADON bit is set. Disregard the warning, because we are not using stimulus file.




    -- ADC_18F4580.scl
    -- Hand-generated by j_doin, 9/9/2005 20:34:13
    -- MPLAB v7.21
    --
    -- Revision history:
    -- v1.6 sep/11/2005 streamlined A2D_CONVERTER, with A/D timing error detection.
    --
    -- This ADC model runs for PIC18F series. It monitors the
    -- ADCON0 ADON & GO signals generated by the internal MPSIM
    -- ADC simulation and overwrites the ADRES values at the
    -- end of A/D conversion. The sampling times and ADC flag bits
    -- are simulated by the internal ADC peripheral core.
    -- This model also detects invalid sampling time and ADC config errors.
    --
    -- The datapoints are taken from a textfile that is read by the WAVEFORM process.
    --

    configuration for "pic18f4580" is
    end configuration;


    testbench for "pic18f4580" is
    begin

    WAVEFORM: process is
    -- read a raw data file of points, and continuously scans from the
    -- start to end of the file.
    file data_file : text;
    variable status : file_open_status;
    variable data_line: line;
    variable sample_time : time;
    variable wait_time : time;
    variable CH0_data_point : integer;
    variable filler : integer;
    begin
    sample_time := 10 us; -- default sample time: 100KSPS
    loop
    file_open(status, data_file, "datapoints.txt", read_mode);
    if status == open_ok then
    while endfile(data_file) == false loop
    readline(data_file, data_line);
    if match(data_line, "") == true then -- skip empty line
    elsif match(data_line, "--") == true then -- skip comments
    elsif match(data_line, "//") == true then -- skip comments
    elsif match(data_line, "time") == true then -- process cmd "time"
    read(data_line, filler); -- discard string "time"
    read(data_line, sample_time); -- read sample time
    elsif match(data_line, "wait") == true then -- process cmd "wait"
    read(data_line, filler); -- discard string "wait"
    assert match(data_line, "for") -- check syntax of "wait for"
    report "error in file datapoints.txt : [wait for] expected."
    severity failure;
    read(data_line, filler); -- discard string "for"
    read(data_line, wait_time); -- read wait time
    wait for wait_time; -- wait for the sample time
    else
    while match(data_line, "") == false loop
    if match(data_line, "--") == true then -- skip end line comments
    exit; -- skip to next line
    elsif match(data_line, "//") == true then -- skip end line comments
    exit; -- skip to next line
    else
    wait for sample_time; -- wait for next sample
    read(data_line, CH0_data_point); -- get data point
    end if;
    end loop;
    end if;
    end loop;
    file_close(data_file); -- end-of-file: close to reopen.
    end if;
    end loop;
    wait;
    end process WAVEFORM;

    A2D_CONVERTER: process is
    variable sampling_voltage : integer;
    variable AD_ERROR : boolean := false;
    variable AD_RUNNING : boolean := false;
    variable conv_started : boolean := false;
    variable conv_time : time;
    variable sampling_time : time;
    variable min_conv_time : time;
    constant TACQ_time : time := 0 us; -- automatic acquisition time
    begin
    -- Combinatorial circuit for detecting A/D sampling and end-of-conversion.
    -- A/D error is flagged if ADON & GO bits set at the same time.
    -- Insufficient sampling times and conversion times are flagged as warnings.
    min_conv_time := TACQ_time + 17.6 us; -- assumes minimum TAD of 1.6µs
    loop
    wait for 1 ic; -- run on every cycle
    if ADCON0.ADON == '1' then
    if AD_ERROR == false then
    if ADCON0.GO_nDONE == '1' then
    if AD_RUNNING then
    if conv_started then
    conv_time := conv_time + 1 ic;
    else
    conv_time := 0 us;
    conv_started := true;
    end if;
    if conv_time <= TACQ_time then
    -- insert here the A/D channel selection
    sampling_voltage := CH0_data_point; -- sample input voltage
    end if;
    else
    AD_ERROR := true;
    report "ADC-SCL model: Illegal ADCON0.ADON & ADCON0.GO set at the same cycle!"
    severity warning;
    end if;
    else
    if conv_started then
    if sampling_time < 12.8 us then
    report "ADC-SCL model: Insufficient sampling time detected!"
    severity warning;
    elsif conv_time >= min_conv_time then
    -- update the value from the selected channel
    if ADCON2.ADFM == '0' then -- left justified
    ADRESH <= sampling_voltage / 4;
    ADRESL <= sampling_voltage * 64;
    else -- right justified
    ADRESH <= sampling_voltage / 256;
    ADRESL <= sampling_voltage;
    end if;
    else
    report "ADC-SCL model: Insufficient conversion time detected!"
    severity warning;
    end if;
    conv_started := false;
    sampling_time := 0 us;
    else
    sampling_time := sampling_time + 1 ic;
    end if;
    end if;
    end if;
    AD_RUNNING := true;
    else
    assert ADCON0.GO_nDONE == '0'
    report "ADC-SCL model: ADCON0.GO set with ADCON0.ADON = 0!"
    severity warning;
    -- reset control variables
    AD_RUNNING := false;
    AD_ERROR := false;
    conv_started := false;
    sampling_time := 0 us;
    conv_time := 0 us;
    end if;
    end loop;
    wait; -- for 1 ic;
    end process A2D_CONVERTER;

    end testbench;




    The WAVEFORM process reads all datapoints and starts over, generating a periodic discrete waveform.
    A sample textfile for the datapoints is as follows (cut/paste in a file named "datapoints.txt") :


    time 100 us // 100KSPS
    // Long lines are possible:
    1 2 3 4 5 6 7 8
    9 10 11 12 13 14 15
    // next line is ignored

    -- this is a comment also
    -- next we have a pulse
    100 110 150 250 480 800 960 1023
    wait for 400 us
    1023 1000 900 700 650 600 580 550 510 480
    400 300 210 128 96 80
    wait for 1 ms -- long pause


    The SCL file is attached at the end of this post, with tab indenting instead of spaces (remove the ".txt" from the filename):

    >>> EDITED: Updated the code with newer revision.
    < Message edited by j_doin -- Sep. 11, 2005 1:58:34 PM >
    #6
    Guest
    Super Member
    • Total Posts : 80499
    • Reward points : 0
    • Joined: 2003/01/01 00:00:00
    • Location: 0
    • Status: online
    RE: SCL/VHDL Code repository 2005/09/11 09:58:02 (permalink)
    0
    ADC INJECTION FROM A TEXTFILE - FOR PIC18F SERIES - (FAST VERSION)

    This is a fast version of the ADC for the PIC18F. This model does not check for A/D timing errors or A/D config errors.
    It runs 2x as fast as the previous model. Unless your simulation is too slow, use the complete version (previous post above).

    Important: Create a text file according to the instructions on the complete code above.

    Only the changed A2D_CONVERTER process is shown below, but the attached file have the complete code:







    A2D_CONVERTER_FAST: process is
        variable conv_started : boolean := false;
    begin
        -- Combinatorial circuit for detecting A/D sampling and end-of-conversion.
        -- Fast version: No A/D errors are detected.
        loop
            wait for 1 ic; -- run on every cycle
            if ADCON0.ADON == '1' then
                if ADCON0.GO_nDONE == '1' then
                    conv_started := true;
                else
                    if conv_started then
                        -- update the value from the selected channel
                        if ADCON2.ADFM == '0' then -- left justified
                            ADRESH <= CH0_data_point / 4;
                            ADRESL <= CH0_data_point * 64;
                        else -- right justified
                            ADRESH <= CH0_data_point / 256;
                            ADRESL <= CH0_data_point;
                        end if;
                        conv_started := false;
                    end if;
                end if;
            else
                -- reset control variables
                conv_started := false;
            end if;
        end loop;
        wait;
    end process A2D_CONVERTER_FAST;


    The SCL file is attached at the end of this post, with tab indenting instead of spaces (remove the ".txt" from the filename):
    post edited by j_doin - 2006/03/10 03:44:28
    #7
    Guest
    Super Member
    • Total Posts : 80499
    • Reward points : 0
    • Joined: 2003/01/01 00:00:00
    • Location: 0
    • Status: online
    RE: SCL/VHDL Code repository 2005/09/19 19:47:46 (permalink)
    0
    EXTERNAL 32768Hz TIMER1 OSCILLATOR FOR PIC16F914

    Apparently in v7.21, for the PIC16F914, the simulator does not simulate TIMER1 incrementing with an external T1OSC. For other PIC16Fs the simulator does increment TIMER1 if you inject a squarewave at T1OSCI, like in the first example at this thread.

    The following SCL model injects the oscillator square wave at T1OSCI and also emulates the TIMER1 incrementing and overflow interrupt generation.


    -- OSC1_32K_914.scl
    -- Hand-Generated by j_doin - 9/17/2005 18:19:32
    --
    -- This testbench has a process _TMR1OSC that generates
    -- an accurate realistic 32768Hz clock into pin T1OSCI of
    -- a PIC16F914 to be used as external clock or TIMER1OSC.
    -- MPSIM on the 16F914 does not simulates TIMER1 oscillator,
    -- so the process _INCTMR1 emulates the operation of the real chip.
    --
    -- The timings are independent from device MPSIM frequency,
    -- but are hand-tuned for 8MHz Internal RC device frequency.
     
    configuration for "pic16f914" is
    end configuration;
     
    testbench for "pic16f914" is
    begin
     
    _TMR1OSC: process is
    -- This process emulates the TMR1OSC by feeding a
    -- square wave input to the pin RA7/T1OSI.
    -- OSC1 freq = 32768.55706Hz, for a clock of 8MHz.
    -- The generator has a pattern of 286 cycles.
    -- No clock startup time is simulated.
        variable iter : integer;
    begin
        RA7 <= '1'; -- value at power-on
        loop
            iter := 1;
            while iter <= 100 loop
                wait for 15.0 us;
                RA7 <= not RA7;
                wait for 16.0 us;
                RA7 <= not RA7;
                iter := iter + 1;
            end loop;
            iter := 1;
            while iter <= 186 loop
                wait for 15.0 us;
                RA7 <= not RA7;
                iter := iter + 1;
            end loop;
        end loop;
        wait;
    end process;
     
    _INCTMR1: process is
    -- This process simulates TIMER1 increment due to T1OSC pulses.
    -- The 16F914 simulator core does not increment TIMER1 with
    -- external pulses at T1OSI.
    -- This process gets the TMR1 value and increments a internal
    -- counter at the falling edge of T1OSI and updates TMR1 value
    -- at the rising edge of T1OSI, simulating the TIMER1 internal operation.
    -- When the counter reaches 16#10000#, TMR1 is reset and TMR1IF is set.
        variable timer_count : integer;
        variable t_L : integer;
        variable t_H : integer;
    begin
        t_L := TMR1L;
        t_H := TMR1H;
        loop
            wait until RA7 == '0';
            t_L := TMR1L;
            t_H := TMR1H;
            timer_count := t_L + t_H * 256;
            wait until RA7 == '1';
            timer_count := timer_count + 1;
            if timer_count == 16#10000# then
                timer_count := 0;
                PIR1.TMR1IF <= '1';
            end if;
            TMR1H <= timer_count / 256;
            TMR1L <= timer_count;
        end loop;
        wait;
    end process;
    end testbench;

     
    post edited by j_doin - 2006/03/10 03:48:11
    #8
    Guest
    Super Member
    • Total Posts : 80499
    • Reward points : 0
    • Joined: 2003/01/01 00:00:00
    • Location: 0
    • Status: online
    RE: SCL/VHDL Code repository 2006/05/03 11:42:02 (permalink)
    0
    Below is a copy of a post left on coding in SCL/VHDL.
     
    I use to complain that VHDL was a clumsy language, but after trying SCL, VHDL looks easy . . .
     
    Attached below is a testbench for a ADS8344, 8 channel, 16-bit ADC. The code is heavily commented with print() statements so I could observe the flow in the output window (on tab MPLAB SIM).
     
    The testbench is a brute force, edge-by-edge, one-hot, state machine to mimic the behavior of the ADC according to the timing diagram of the Texas Instrument/Burr-Brown part. The model supports channel selection (channel values are hard wired into variables initialize at top of process), but not much else. Simple modification of the code would allow differential readback using the SGL/DIF bit of the instruction word. I refer readers to the TI datasheet. Use the code at YOUR OWN RISK, I think it correct, but . . .
     
    The testbench interfaces with the microcontroller via a bit-banged SPI bus on RD4 (SPISDO), RD5 (SPISDI), and RD6 (SPICLK). The ADC's chip select is RE2. I tested the code with an assembly language program in MPLAB and bits shifted in off the SPISDI pin read correctly in a 16-bit buffer.
     
    I suspect that the underlying code describing the Microchip controllers is VHDL (or Verilog) and it should be possible (with some accommodations by Microchip) to code testbenches directly in VHDL rather than the crippled version--aka SCL. (However, access to the VHDL may give away the Microchip designs to competitors, and hence the SCL interface--and VHDL has a steep learning curve). A clock statement like:
     
    if clk'EVENT and clk = '1' then
     
    would have ease the task considerably.
     
    //
    // C:\dge\sims_mc\ADC_dead.scl
    // Generated by SCL Generator ver. 3.22.00.00
    // 5/1/2006 17:28:30
    //

    configuration for "pic18f8722" is
    end configuration;
    testbench for "pic18f8722" is
    begin
    --    process is
    --    begin
    --        wait for 0 ic;
    --        report "Stimulus actions after 0 ic";
    --  if RE2 == '1' then
    --   report "RE2 is high";
    --  else
    --   report "RE2 is low";
    --  end if;
    --        wait;
    --    end process;
     
    --ADS8344: process is
    ADS8344: process (RE2, RD6) is -- can't have both sensitivity
           -- list and wait statements to suspend process
     variable st_cnt : integer := 0;
     variable start : integer; -- or boolean;
     variable A210 : integer;
     variable DMY : integer; -- or boolean;
     variable SGL_DIF: integer; -- or boolean;
     variable PD1 : integer; -- or boolean;
     variable PD0 : integer; -- or boolean;
     variable CH0 : integer := 0;  -- by eights
     variable CH1 : integer := 8191; -- 1/8
     variable CH2 : integer := 16383; -- 2/8 . . .
     variable CH3 : integer := 24575;
     variable CH4 : integer := 32767;
     variable CH5 : integer := 40959;
     variable CH6 : integer := 49151;
     variable CH7 : integer := 65535;
     variable RDBK : integer;
        begin
    --  print (" ");
    --  print ("change in sensitivity list, st_cnt=",st_cnt);
      if RE2 == '1' then
       st_cnt := 0; -- if chip select relaxed, reset state counter
       report "chip select relaxed";
      ----------------------------------------------------
      elsif st_cnt == 0 then
       print ("RE2 == 0, st_cnt=",st_cnt);
             if RD6 == '1' then -- we assume clk idles low
        if RD4 == '1' then -- SPISDO
         start := 1;
        else
         start := 0;
        end if;
        print ("RD6 == 1, start=",start);
        st_cnt := st_cnt + 1;
       end if;
      elsif st_cnt == 1 then
             if RD6 == '0' then  -- advance on falling edge
        print ("RD6 == 0, st_cnt=",st_cnt);
        print ("start=",start);
        st_cnt := st_cnt + 1;
       end if;
      ----------------------------------------------------
      elsif st_cnt == 2 then
             if RD6 == '1' then
        if RD4 == '1' then
         A210 := 4;
        else
         A210 := 0;
        end if;
        print ("A210=",A210);
        st_cnt := st_cnt + 1;
       end if;
      elsif st_cnt == 3 then
             if RD6 == '0' then
        st_cnt := st_cnt + 1;
       end if;
      ----------------------------------------------------
      elsif st_cnt == 4 then
             if RD6 == '1' then
        if RD4 == '1' then
         A210 := A210 + 2;
        else
         A210 := A210 + 0;
        end if;
        print ("A210=",A210);
        st_cnt := st_cnt + 1;
       end if;
      elsif st_cnt == 5 then
             if RD6 == '0' then
        st_cnt := st_cnt + 1;
       end if;
      ----------------------------------------------------
      elsif st_cnt == 6 then
             if RD6 == '1' then
        if RD4 == '1' then
         A210 := A210 + 1;
        else
         A210 := A210 + 0;
        end if;
        print ("A210=",A210);
        st_cnt := st_cnt + 1;
       end if;
      elsif st_cnt == 7 then
             if RD6 == '0' then
        st_cnt := st_cnt + 1;
       end if;
      ----------------------------------------------------
      elsif st_cnt == 8 then
             if RD6 == '1' then
        if RD4 == '1' then
         DMY  := 1;
        else
         DMY  := 0;
        end if;
        print ("DMY=",DMY);
        st_cnt := st_cnt + 1;
       end if;
      elsif st_cnt == 9 then
             if RD6 == '0' then
        st_cnt := st_cnt + 1;
       end if;
      ----------------------------------------------------
      elsif st_cnt == 10 then
             if RD6 == '1' then
        if RD4 == '1' then
         SGL_DIF  := 1;
        else
         SGL_DIF  := 0;
        end if;
        print ("SGL_DIF=",SGL_DIF);
        st_cnt := st_cnt + 1;
       end if;
      elsif st_cnt == 11 then
             if RD6 == '0' then
        st_cnt := st_cnt + 1;
       end if;
      ----------------------------------------------------
      elsif st_cnt == 12 then
             if RD6 == '1' then
        if RD4 == '1' then
         PD1  := 1;
        else
         PD1  := 0;
        end if;
        print ("PD1=",PD1);
        st_cnt := st_cnt + 1;
       end if;
      elsif st_cnt == 13 then
             if RD6 == '0' then
        st_cnt := st_cnt + 1;
       end if;
      ----------------------------------------------------
      elsif st_cnt == 14 then
             if RD6 == '1' then -- capture last bit on rising edge
        if RD4 == '1' then
         PD0  := 1;
        else
         PD0  := 0;
        end if;
        print ("PD0=",PD0);
        st_cnt := st_cnt + 1;
       end if;
      elsif st_cnt == 15 then
             if RD6 == '0' then
        st_cnt := st_cnt + 1;
       end if;
      ----------------------------------------------------
      -- we have 8-bit control byte
      -- select readback value by A2,A1,A0 address
      ----------------------------------------------------
      elsif st_cnt == 16 then
             if RD6 == '1' then -- inter command/response clock cycle
        st_cnt := st_cnt + 1;
       end if;
      elsif st_cnt == 17 then
             if RD6 == '0' then -- changes on falling edge
        if A210 == 0 then
         RDBK := CH0;
        elsif A210 == 1 then
         RDBK := CH1;
        elsif A210 == 2 then
         RDBK := CH2;
        elsif A210 == 3 then
         RDBK := CH3;
     
        elsif A210 == 4 then
         RDBK := CH4;
        elsif A210 == 5 then
         RDBK := CH5;
        elsif A210 == 6 then
         RDBK := CH6;
        elsif A210 == 7 then
         RDBK := CH7;
        end if;
        print ("st_cnt=",st_cnt);
        print (" start=",start);
        print ("  A210=",A210);
        print ("  RDBK=",RDBK);
     
        if RDBK > 32767 then -- start readback on SPISDI
         RD5 <= '1';   -- post bit high
         RDBK := RDBK - 32768;
        else
         RD5 <= '0';   -- post bit low
        end if;
       print ("  RDBK=",RDBK);
       st_cnt := st_cnt + 1;  -- bump and wait
       end if;
      -----------------------------
      elsif st_cnt == 18 then
             if RD6 == '1' then  -- advance on rising edge
        st_cnt := st_cnt + 1;
       end if;
      ----------------------------------------------------
      elsif st_cnt == 19 then
             if RD6 == '0' then  -- change on falling edge
        if RDBK > 16383 then
         RD5 <= '1';
         RDBK := RDBK - 16384;
        else
         RD5 <= '0';
        end if;
        print ("  RDBK=",RDBK);
        st_cnt := st_cnt + 1;
       end if;
      -----------------------------
      elsif st_cnt == 20 then
             if RD6 == '1' then
        st_cnt := st_cnt + 1;
       end if;
      ----------------------------------------------------
      elsif st_cnt == 21 then
             if RD6 == '0' then
        if RDBK > 8191 then
         RD5 <= '1';
         RDBK := RDBK - 8192;
        else
         RD5 <= '0';
        end if;
        print ("  RDBK=",RDBK);
        st_cnt := st_cnt + 1;
       end if;
      -----------------------------
      elsif st_cnt == 22 then
             if RD6 == '1' then
        st_cnt := st_cnt + 1;
       end if;
      ----------------------------------------------------
      elsif st_cnt == 23 then
             if RD6 == '0' then
        if RDBK > 4095 then
         RD5 <= '1';
         RDBK := RDBK - 4096;
        else
         RD5 <= '0';
        end if;
        print ("  RDBK=",RDBK);
        st_cnt := st_cnt + 1;
       end if;
      -----------------------------
      elsif st_cnt == 24 then
             if RD6 == '1' then
        st_cnt := st_cnt + 1;
       end if;
      ----------------------------------------------------
      elsif st_cnt == 25 then
             if RD6 == '0' then
        if RDBK > 2047 then
         RD5 <= '1';
         RDBK := RDBK - 2048;
        else
         RD5 <= '0';
        end if;
        print ("  RDBK=",RDBK);
        st_cnt := st_cnt + 1;
       end if;
      -----------------------------
      elsif st_cnt == 26 then
             if RD6 == '1' then
        st_cnt := st_cnt + 1;
       end if;
      ----------------------------------------------------
      elsif st_cnt == 27 then
             if RD6 == '0' then
        if RDBK > 1023 then
         RD5 <= '1';
         RDBK := RDBK - 1024;
        else
         RD5 <= '0';
        end if;
        print ("  RDBK=",RDBK);
        st_cnt := st_cnt + 1;
       end if;
      -----------------------------
      elsif st_cnt == 28 then
             if RD6 == '1' then
        st_cnt := st_cnt + 1;
       end if;
      ----------------------------------------------------
      elsif st_cnt == 29 then
             if RD6 == '0' then
        if RDBK > 511 then
         RD5 <= '1';
         RDBK := RDBK - 512;
        else
         RD5 <= '0';
        end if;
        print ("  RDBK=",RDBK);
        st_cnt := st_cnt + 1;
       end if;
      -----------------------------
      elsif st_cnt == 30 then
             if RD6 == '1' then
        st_cnt := st_cnt + 1;
       end if;
      ----------------------------------------------------
      elsif st_cnt == 31 then
             if RD6 == '0' then
        if RDBK > 255 then
         RD5 <= '1';
         RDBK := RDBK - 256;
        else
         RD5 <= '0';
        end if;
        print ("  RDBK=",RDBK);
        st_cnt := st_cnt + 1;
       end if;
      -----------------------------
      elsif st_cnt == 32 then
             if RD6 == '1' then
        st_cnt := st_cnt + 1;
       end if;
      ----------------------------------------------------
      elsif st_cnt == 33 then
             if RD6 == '0' then
        if RDBK > 127 then
         RD5 <= '1';
         RDBK := RDBK - 128;
        else
         RD5 <= '0';
        end if;
        print ("  RDBK=",RDBK);
        st_cnt := st_cnt + 1;
       end if;
      -----------------------------
      elsif st_cnt == 34 then
             if RD6 == '1' then
        st_cnt := st_cnt + 1;
       end if;
      ----------------------------------------------------
      elsif st_cnt == 35 then
             if RD6 == '0' then
        if RDBK > 63 then
         RD5 <= '1';
         RDBK := RDBK - 64;
        else
         RD5 <= '0';
        end if;
        print ("  RDBK=",RDBK);
        st_cnt := st_cnt + 1;
       end if;
      -----------------------------
      elsif st_cnt == 36 then
             if RD6 == '1' then
        st_cnt := st_cnt + 1;
       end if;
      ----------------------------------------------------
      elsif st_cnt == 37 then
             if RD6 == '0' then
        if RDBK > 31 then
         RD5 <= '1';
         RDBK := RDBK - 32;
        else
         RD5 <= '0';
        end if;
        print ("  RDBK=",RDBK);
        st_cnt := st_cnt + 1;
       end if;
      -----------------------------
      elsif st_cnt == 38 then
             if RD6 == '1' then
        st_cnt := st_cnt + 1;
       end if;
      ----------------------------------------------------
      elsif st_cnt == 39 then
             if RD6 == '0' then
        if RDBK > 15 then
         RD5 <= '1';
         RDBK := RDBK - 16;
        else
         RD5 <= '0';
        end if;
        print ("  RDBK=",RDBK);
        st_cnt := st_cnt + 1;
       end if;
      -----------------------------
      elsif st_cnt == 40 then
             if RD6 == '1' then
        st_cnt := st_cnt + 1;
       end if;
      ----------------------------------------------------
      elsif st_cnt == 41 then
             if RD6 == '0' then
        if RDBK > 7 then
         RD5 <= '1';
         RDBK := RDBK - 8;
        else
         RD5 <= '0';
        end if;
        print ("  RDBK=",RDBK);
        st_cnt := st_cnt + 1;
       end if;
      -----------------------------
      elsif st_cnt == 42 then
             if RD6 == '1' then
        st_cnt := st_cnt + 1;
       end if;
      ----------------------------------------------------
      elsif st_cnt == 43 then
             if RD6 == '0' then
        if RDBK > 3 then
         RD5 <= '1';
         RDBK := RDBK - 4;
        else
         RD5 <= '0';
        end if;
        print ("  RDBK=",RDBK);
        st_cnt := st_cnt + 1;
       end if;
      -----------------------------
      elsif st_cnt == 44 then
             if RD6 == '1' then
        st_cnt := st_cnt + 1;
       end if;
      ----------------------------------------------------
      elsif st_cnt == 45 then
             if RD6 == '0' then
        if RDBK > 1 then
         RD5 <= '1';
         RDBK := RDBK - 2;
        else
         RD5 <= '0';
        end if;
        print ("  RDBK=",RDBK);
        st_cnt := st_cnt + 1;
       end if;
      -----------------------------
      elsif st_cnt == 46 then
             if RD6 == '1' then
        st_cnt := st_cnt + 1;
       end if;
      ----------------------------------------------------
      elsif st_cnt == 47 then
             if RD6 == '0' then
        if RDBK > 0 then
         RD5 <= '1';
         RDBK := RDBK - 1;
        else
         RD5 <= '0';
        end if;
        print ("  RDBK=",RDBK); -- if not zero, trouble
        st_cnt := st_cnt + 1;
       end if;
      -----------------------------
      elsif st_cnt == 48 then
             if RD6 == '1' then
        st_cnt := st_cnt + 1;
       end if;
      ----------------------------------------------------
      elsif st_cnt == 49 then
       print ("SPICLK idles high,st_cnt=",st_cnt);
      end if;
        end process ADS8344;
    end testbench;
     
    #9
    hutorny
    Super Member
    • Total Posts : 345
    • Reward points : 0
    • Joined: 2003/11/07 12:47:29
    • Status: offline
    RE: SCL/VHDL Code repository 2006/05/04 01:25:03 (permalink)
    0
    // Simulation of a USART based RS 232 transmitter
    // Written by Eugene M. Hutorny
    // This script has been proven to work only for software implementation of RS 232 receiver
    // Three signals are in use: INT0 (RX), RC7 (CTS) and RA0 (RTS)
    // Signal levels are controlled by ISPACE and OSPACE constants
    // Data read from file "usartdata.txt" line by line and for each line
    // RTS is set SPACE, line is read (as decimal) and sent, and then RTS is set MARK
    // After some idle time next line is read and process is repeated
    // Data transmission is CTS controlled and simulate buffered USART chip as the following:
    // Wait CTS, send up to 16 bytes, repeat
    configuration for "pic16f690" is
        constant ISPACE     : bit := 1;         // Input not inverted
        constant IMARK      : bit := 0;
        constant OSPACE     : bit := 0;         // Output is inverted
        constant OMARK      : bit := 1;
        constant DataLength : integer := 8;
        constant BaudRate   : integer := 115200;
        constant StopBits   : integer := 1;     // Valid values are 1 and 2
        constant UART_TX_Buff: integer := 16;   // Length of simulated USART TX Buffer
        constant DataFileName: string := "usartdata.txt";
       //alias CTS : bit is RC7;
       //alias RTS : bit is RA0;
       //alias RX : bit is INT0;
        shared label AS_IDLE; // Entering this label indicaties that the application is ready
    end configuration;
     
    testbench for "pic16f690" is
      begin
       startup: process is
          begin
           RA0 <= IMARK; // RTS <= MARK
           INT0 <= IMARK; // RX <= MARK
            wait;
         end process;

        readlines: process is
            file DataFile : text;
             variable status : file_open_status;
             variable DataLine : line;
             variable CommentMsg : string;
           begin
            file_open(status, DataFile, DataFileName, read_mode);
             if status != open_ok then
                print("Input file ", DataFileName, " not found");
                 wait;
             end if;
             wait until PCL == AS_IDLE;
             while endfile(DataFile) == false loop
                readline(DataFile, DataLine);
                 if match(DataLine, "") == true then      // skip empty line
                 elsif match(DataLine, "//") == true then // dump comments to SIM log
                    read(DataLine,CommentMsg);
                     report CommentMsg;
                 else
                    //report "RTS<=SPACE";
                    RA0 <= ISPACE;                       // RTS <= SPACE
                     wait until RA0 == IMARK;
                    //report "RTS==MARK";
                 end if;
             end loop;
            file_close(DataFile);
            //wait until PCL == 0;
             wait;
           end process;

        sendline: process is
             variable BitDuration : time;
             variable ShiftReg : integer;
             variable CurrentBit : integer;
             variable BitCount : integer := 0;
             variable ByteCount : integer := 0;
             variable ByteToSend : integer := 0;
             variable Octet : integer := 0;
             variable Timer : time;
             variable RightNow : time;
           begin
            ByteCount := 0;
            BitDuration := 1 sec / BaudRate;
             wait until RA0 == ISPACE;
            //report "RTS=space";
            ByteToSend := 1;
            read(DataLine, ByteToSend);
             while ByteToSend != 1 loop
                 if ByteCount == UART_TX_Buff then
                    ByteCount := 0;
                 end if;
                 if ByteCount == 0 then
                     if RC7 != OSPACE then
                        //report "waiting CTS";
                         wait until RC7 == OSPACE;
                     end if;
                   //report "CTS=SPACE";
                 end if;
                //print("sending DATA[", ByteCount, "]==", ByteToSend);
                ShiftReg := ByteToSend;
                BitCount := 0;
                // Send Byte
                INT0 <= ISPACE; // RX <= SPACE; // Start bit
                Timer := now();
                 wait for BitDuration;
                Timer := Timer + BitDuration;
                 while BitCount < DataLength loop
                    CurrentBit := ShiftReg / 2;              // shift register implementation
                    CurrentBit := ShiftReg - 2 * CurrentBit; // based on integer division (modulus 2)
                    ShiftReg := ShiftReg / 2;
                     if CurrentBit == 0 then
                        INT0 <= ISPACE; // RX <= SPACE;
                     else
                        INT0 <= IMARK; // RX <= MARK;
                     end if;
                    Timer := Timer + BitDuration; // the following three lines prevent from
                    RightNow := now();            // accumulation error in bit timing
                     wait for Timer RightNow;      // for some reason Timer - now() is not supported
                    BitCount := BitCount + 1;
                 end loop;
                //report "STOP BIT";
                INT0 <= IMARK; // RX <= MARK;
                 if StopBits == 2 then
                     wait for BitDuration;
                 end if;
                 wait for BitDuration + 1 ic;
                ByteCount := ByteCount + 1;
                ByteToSend := 1;
                read(DataLine, ByteToSend);
             end loop;
            RA0 <= IMARK; // RTS <= MARK
            //report "RTS=MARK";
           end process;
    end testbench;
     






    Sample data file (usartdata.txt)

    //HELLO
    72 69 76 76 79 13
    //WORLD
    87 79 82 76 68 13







    Signal waveforms

    post edited by hutorny - 2006/05/04 01:32:41

    Attached Image(s)

    #10
    daver_intrepid
    Starting Member
    • Total Posts : 40
    • Reward points : 0
    • Joined: 2007/03/15 10:15:24
    • Location: 0
    • Status: offline
    RE: SCL/VHDL Code repository 2007/08/01 07:19:30 (permalink)
    0
    Here is some code for simulating a transceiver connected to CCP1 and CCP2. Basically it makes RC2 equal to RC1 with a 20 uS lag.

    configuration for "pic18f25j10" is
    end configuration;


    testbench for "pic18f25j10" is
    begin
        process is
       
        variable lastRC1 : integer;
        variable currnetRC1 : integer;
        begin
            wait for 0 us;
            report "Running Tx Simulation";
            loop
            if RC1 == '1' then
                currnetRC1 := 1;
            else
                currnetRC1 := 0;
            end if;
           
            if lastRC1 /= currnetRC1 then
                wait for 19 us;
                RC2 <= RC1;
            end if;
       
        if RC1 == '1' then
                lastRC1 := 1;
            else
                lastRC1 := 0;
            end if;
           
           
            wait for 1 us;
            end loop;
           
            wait;
        end process;

    end testbench;


    #11
    Jump to:
    © 2017 APG vNext Commercial Version 4.5