The C language and portable C programs do not in any way require a Von Neumann architecture. In fact with the modern trend for phone/tablet/desktop/server OSes to use W^X memory permissions they effectively mandate programs written in Harvard-compatible style even if they technically have code and data in the same address space.
Once instruction sets got features such as index (or base) registers and register indirect addressing (including stack addressing) instead of absolute addressing (including for indirect jumps/subroutine calls) there was no longer any need to support self-modifying code during execution of the program itself, and Von Neumann architecture is not required except for initial loading of the program code into memory by the OS.
I'd think most modern instruction sets are easily capable of running with code and data in truly different address spaces.
The only real difficulty is in loading constant data and especially constant tables from program space. Microcontroller ISAs such as AVR have special instructions for program space loads. Any ISA where the PC is a GPR (PDP-11, VAX, arm32) or that has an explicit PC-relative addressing mode (preferably indexed) such as 68000 make it easy to detect that a memory reference is PC-relative and do it in the program space instead of the data space.
Arm64 with ADR and ADRP and RISC-V with AUIPC make it tricky because hardware would have to track that a GPR contains a pointer derived from the PC. x86 and PowerPC make it even more difficult, because the only way to get the PC value is to do a fake function call to the next instruction (or to keep return stack prediction happy, to a real function that just saves the return address then returns). On these ISAs you're probably better off assembling all constants using load immediate and shifts, and arrays or tables of constants using computed jumps to load immediate instructions.
In short, using a conventional modern ISA with Harvard architecture is doable if you want to.