Honestly, there's absolutely nothing that would prevent you from learning HDL. There are a number of excellent development boards and tutorials. Start here:

http://www.xilinx.com/university/students/index.htm

The issue with doing higher-level work is that you really need to understand circuit design and implementation. A lot of what you do in an FPGA is to type out text that looks like code but in reality is a "secret contract" with the compiler for it to "infer" the circuit you want. In many ways you could say that there are idioms that you learn that will result in specific circuit constructs once they go through one turn of the wheel.

Then there's the issue of optimization. Sometimes you just don't get the performance you want and have to resort to, effectively, hand-wiring stuff in code. Whether VHDL or Verilog, you have the ability to literally hand-wire FPGA internals to build circuits that usually perform or place better than the what the tools can do:

(sorry, this is long)

module ADDER
#(parameter WIDTH = 8)
(
input wire CLK,
input wire CE,
input wire RST,
input wire CIN,
input wire [WIDTH - 1:0] A,
input wire [WIDTH - 1:0] B,
output wire [WIDTH:0] SUM
);

genvar i;

wire [WIDTH - 1:0] xor2;
wire [WIDTH:0] cy;
wire [WIDTH - 1:0] xorcy;

assign cy[0] = CIN;

generate
for(i=0; i <= WIDTH; i=i+1) begin:BIT
if(i != WIDTH)begin:_
myXOR2 x(.O(xor2[i]), .I0(A[i]), .I1(B[i]));
MUXCY m(.O(cy[i+1]), .CI(cy[i]), .DI(A[i]), .S(xor2[i]));
XORCY xc(.O(xorcy[i]), .CI(cy[i]), .LI(xor2[i]));
FDRE f(.Q(SUM[i]), .C(CLK), .CE(CE), .D(xorcy[i]), .R(RST));
end
else begin:_
FDRE f(.Q(SUM[i]), .C(CLK), .CE(CE), .D(cy[i]), .R(RST));
end
end
endgenerate

//synthesis attribute RLOC of BIT[0]._.x is X0Y0
//synthesis attribute RLOC of BIT[1]._.x is X0Y0
//synthesis attribute RLOC of BIT[2]._.x is X0Y1
//synthesis attribute RLOC of BIT[3]._.x is X0Y1
//synthesis attribute RLOC of BIT[4]._.x is X0Y2
//synthesis attribute RLOC of BIT[5]._.x is X0Y2
//synthesis attribute RLOC of BIT[6]._.x is X0Y3
//synthesis attribute RLOC of BIT[7]._.x is X0Y3
//synthesis attribute RLOC of BIT[8]._.x is X0Y4
//synthesis attribute RLOC of BIT[9]._.x is X0Y4
//synthesis attribute RLOC of BIT[10]._.x is X0Y5
//synthesis attribute RLOC of BIT[11]._.x is X0Y5
//synthesis attribute RLOC of BIT[12]._.x is X0Y6
//synthesis attribute RLOC of BIT[13]._.x is X0Y6
//synthesis attribute RLOC of BIT[14]._.x is X0Y7
//synthesis attribute RLOC of BIT[15]._.x is X0Y7
//synthesis attribute RLOC of BIT[16]._.x is X0Y8
//synthesis attribute RLOC of BIT[17]._.x is X0Y8
//synthesis attribute RLOC of BIT[18]._.x is X0Y9
//synthesis attribute RLOC of BIT[19]._.x is X0Y9
//synthesis attribute RLOC of BIT[20]._.x is X0Y10
//synthesis attribute RLOC of BIT[21]._.x is X0Y10
//synthesis attribute RLOC of BIT[22]._.x is X0Y11
//synthesis attribute RLOC of BIT[23]._.x is X0Y11
//synthesis attribute RLOC of BIT[24]._.x is X0Y12
//synthesis attribute RLOC of BIT[25]._.x is X0Y12
//synthesis attribute RLOC of BIT[26]._.x is X0Y13
//synthesis attribute RLOC of BIT[27]._.x is X0Y13
//synthesis attribute RLOC of BIT[28]._.x is X0Y14
//synthesis attribute RLOC of BIT[29]._.x is X0Y14
//synthesis attribute RLOC of BIT[30]._.x is X0Y15
//synthesis attribute RLOC of BIT[31]._.x is X0Y15
<... a bunch more of this snipped due to HN message length constraints ...>
endmodule

//synthesis attribute LUT_MAP of myXOR2 is YES;
module myXOR2
(
output O,
input I0,
input I1
);

assign O = I0 ^ I1;

endmodule

That's the kind of thing you have to do if you have to squeeze the last MHz in performance out of an FPGA. That code was part of an FIR filter I designed that, about ten years ago, could not break 150MHz using the "hey compiler, you figure it out" approach. If I remember correctly, the hand-wired filter easily did 200MHz.