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;