Meditation, The Art of Exploitation

Thinking? At last I have discovered it--thought; this alone is inseparable from me. I am, I exist--that is certain. But for how long? For as long as I am thinking. For it could be, that were I totally to cease from thinking, I should totally cease to exist....I am, then, in the strict sense only a thing that thinks.

Sunday, July 06, 2008

Windows Win32 APIs: changes from win95/98/2000 to XP

I needed to code a simple http downloader, a dialog based win32 application. This application provides a simple UI to allow user to put in an URL and click a button to start downloading. Initially I also want to provide a RichEdit text area to log transactions and messages for debugging/diagnosis purpose.

I used to program win32 applications on windows 2000 platform with visual c++ 6.0, using a CmnHdr.H dialog template. This header file has some convenience macros to easily define win32 message handlers. The first problem I encountered is on Windows XP, this header file no longer works well. It can still be made to work after some modifications but the template needs adjustment. It made more sense to throw away to header file and template and just code the dialog box directly using this example code:


#define STRICT
#define WIN32_LEAN_AND_MEAN
#include
#include "resource.h"

BOOL CALLBACK DialogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) {
switch (message) {
case WM_INITDIALOG:
return (TRUE);
case WM_COMMAND:
switch (wParam) {
case IDOK:
case IDCANCEL:
EndDialog(hDlg, TRUE);
return (TRUE);
}
break;
}
return (FALSE);
}

int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
int ReturnValue;
ReturnValue = DialogBoxParam(NULL, MAKEINTRESOURCE(IDD_DIALOG1), NULL, DialogProc, NULL);
return 0;
}



The 2nd problem really puzzled me. My dialogbox won't show up no matter what. DialogBox returned -1 but GetLastError returned 0. Debugging into the win32 library code quickly showed me that there is something intricately wrong and -1 is returned from win32 internals. After spending many hours to resolve this issue, I finally found the solution from the win32.programmer.ui newsgroups. The answer is an win32 API called InitCommonControlsEx. On WinXP, one must call this API to use standard controls, otherwise the syptom is exactly as I described, the dialogbox won't show up (for some people, the dialog box would show up but without controls).

References:
1. http://simplesamples.info/Windows/DlgHello.php
2. http://msdn.microsoft.com/en-us/library/bb775697(VS.85).aspx

Wednesday, May 14, 2008

C++: static initialization order fiasco and mixed language programming

As c++ faq-lite puts it, 'static initialization order fiasco' is "a subtle way to crash your program" (1). The C++ run time system exhibits a phenomenon, static objects in the global scope can initialize in arbitrary order between different builds. In other words, if there are two static objects in the global scope called A and B in a program, in one build with a compiler on a platform, A could initialize before B but on another platform with another compiler in a different build, B could initialize before A. This could happen even on a single platform with a single compiler but different build options (e.g. optimization levels)

The similarity of compiler dependency is striking between this problem and the RVO problem in the previous entry. And *similarly* any failure is a indication of coding defect by the programmer. A hypothetical scenario with the 'static initialization order fiasco' is such:




A.hpp
struct A{
static bool initialized;
A() : initialized(true) {}
};
A.cpp
bool A::initialized;

B.hpp
struct B{
B(){
if(A::initialized) x = 1;
else x = 0;
}
static int x;
};
int B:x;

C.cpp
void foo(){
int fiasco = B:x;
}




What should be the value of fiasco inside foo when the program runs? It could be either 0 or 1. Thus the program exhibits unreliable behavior.

Ok, now we know what's 'static initialization order fiasco', what does it have to do with mixed language programming? In mixed language programming, specifically between C++ and something else, let's say G, if G's run time system is dominate and starting user code is written in G (compiled and linked with G compiler/linker), G should refrain from calling any C++ code that may reference static objects (e.g. void foo()). Take a look at this bug.

Process received signal 11 (SIGSEGV)
__CPR123____ls__tm__30_Q2_3std20char_traits__tm__2_c__3stdFRQ2_3std25basic_ostre/opt/ctl/CC/5.5.0.9/include/ostream+??? (???) at ostream
c_strings_+0x00F0 (0x1004AF0) at A.C:48
stringtest_+0x0874 (0x1022374) at B.F90:77

Here is A.C:48
cout << "\n\n-- entering c_strings" << endl;

http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.12

Tuesday, May 13, 2008

C++: return value optimization (RVO) and reference class member

Recently I was experimenting with expression templates (1,2), I was making good progress with my toy code until suddenly I started getting correct answer from optimized build (-O2) and segmentation faults from debug build (-O0). With judicious object creation/destruction tracer code, it's clear to me return value optimization (3,4) or RVO is playing a trick here. This is troublesome as the program behavior depends on unreliable optimization from a compiler. When RVO optimization is not available, the program produces wrong result. This syndrome typically means there is a problem in the source code that binds variables (reference or pointer type) to temporary stack object and later references it while the temporary stack object has gone out of scope and become invalid.

The source code will make the problem clearer and easier to explain:


#include < iostream>
using namespace std;

template < typename E>
struct expr {
double eval() const {
return e.eval();
};
double eval() {
return e.eval();
};

expr(const E & e) : e(e) {}
E e;
};

class Literal {
public:
Literal(double v) : val_(v) {}
double eval() const { return val_; }
private:
const double val_;
};

class Variable {
public:
Variable(double& v) : val_(v) { cout << &val_ << " default initialized " << id++ << endl;}
Variable(const Variable & v) : val_(*&(v.val_)) { cout << &val_ << " copy initialized " << this << ' ' << *(double *)this << ' ' << id++ << endl; }
~Variable() { cout << &val_ << " destroyed" << endl; }
double eval() const { cout << &val_ << " eval " << this << ' ' << &(this->val_) << endl; return val_; }
private:
double& val_;
static int id;
};

int Variable::id = 0;

// Abstraction of a binary expression
template < typename expr1, typename expr2, typename binop>
struct BinaryExpr {
double eval() const {
return binop::eval(_expr1.eval(), _expr2.eval());
}
BinaryExpr(const expr1 & e1, const expr2 & e2)
: _expr1(e1),_expr2(e2) {}
BinaryExpr(const BinaryExpr & be) : _expr1(be._expr1), _expr2(be._expr2) { cout << "BE copy initiailized" << endl; }
private:
const expr1 & _expr1;
// Cannot use reference here (const expr1 &) because _expr1 may refer to a temporary stack object and becomes invalid when the bound object went ou
t of scope later
const expr2 & _expr2;
};

// Abstraction of semantic plus operation '+'
struct plusOp {
static double eval (const double & d1, const double & d2) {
return d1 + d2;
}
};
// Expression Traits class, convert primitive type to Literal type
template < typename T>
struct ExprTraits
{
typedef T type;
};

template <>
struct ExprTraits< int>
{
typedef Literal type;
};

template <>
struct ExprTraits< double>
{
typedef Literal type;
};

// This is the critical piece in building expression template
// An overloaded operator builds an expression that can be evaluated later.
template < typename expr1, typename expr2>
expr< BinaryExpr< typename ExprTraits< expr1>::type, typename ExprTraits< expr2>::type, plusOp> >
operator + (const expr1 & e1, const expr2 & e2){
typedef BinaryExpr< typename ExprTraits< expr1>::type, typename ExprTraits< expr2>::type, plusOp> ExprT;
return expr< ExprT>(ExprT(typename ExprTraits< expr1>::type(e1), typename ExprTraits< expr2>::type(e2)));
}

template < typename E>
double eval(expr< E> e){
return e.eval();
}

int main(){

double x = 10;
Variable v(x);
Literal l(3);
cout << &x << ' ' << x << endl;

// evaluate expressions
cout << sizeof(v) << ' ' << eval(v + 10.0) << endl;
}



The problem as indicated in the source code comment, is with the member variables _expr1, _expr2 of BinaryExpr. BinaryExpr can be constructed from 2 participating expressions (e1, e2). When _expr1 is declared as const expr1 &, it binds to the first argument e1. This is the problem, when RVO is not available, it's conceivable (as shown in this example) that BinaryExpr's constructor can be invoked with temporary stack objects as arguments. When it happens, _expr1 is bound to a stack local object and later on causes erratic program behavior when referenced as the stack local object went out of scope. To fix this, a deep copy (more precisely until nothing is bound to temporary objects that can go out of scope independently) is required.

Careful readers may raise the question why in Variable, there is a 'double & val_'. Will this be a problem? Yes and No. Yes, in general, it holds true that a reference or a pointer type variable (regardless if it's a class member variable or not) when bound to a temporary stack local variable should never *dereference* that object later when the object goes out of scope. No, in this toy program, all 'double & val_' in all Variable instances are carefully referenced to '10.0' in the expression in main function and '10.0' only goes out of scope when eval() finishes and therefore the code is safe from the dreaded 'dereferencing dead (out of scope) object' problem.

References:
1. http://www.ddj.com/cpp/184401627
2. http://ubiety.uwaterloo.ca/~tveldhui/papers/Expression-Templates/exprtmpl.html
3. http://www.cs.cmu.edu/~gilpin/c++/performance.html
4. http://msdn.microsoft.com/en-us/library/ms364057(VS.80).aspx#nrvo_cpp05_topic4

Monday, April 07, 2008

FPGA: LCD display from RS232 interface

After more than a month's of studying of verilog and fpga design, I am proud to present the result of my first mini-project. Controlling Spartan3A LCD display with RS232 serial interface from a host computer. The setup is very simple:


minicom (linux host) <------> RS232 (J27) <-------> LCD (DISP1)


I used the 2 serial interface modules from fpga4fun.com (async_receiver and async_transmitter). I implemented the main serial to lcd control module and the lcd display module. The lcd display module implementation is especially gratifying after it was completed. I learnt a great deal about finite state machine implementation in verilog and how sequential/combinatorial logic work together. Here is the state machine of the lcd controller (drawn using qfsm):



As you can see, state 2,3,4,5 (I didn't use one-hot encoding) all require that certain signal lines driven at a certain value for a certain amount of time (or number of clks). To achieve such kind of effect, one need to combine a FSM with a counter. The technical details of the requirements can be found in Spartan3A revion D's user's guide (ug334.pdf) in the LCD section.

The implementation of the lcd controller follows:


module lcd_controller (clk, rst_n, data_ready, rx_data, lcd_rs, lcd_rw, lcd_e, lcd_4, lcd_5, lcd_6, lcd_7);

parameter k = 18;
// in register_input mode, the input doesn't have to stay valid
// while the character is being transmitted
parameter register_input = 1;
parameter clr = 8'h0A;

input clk; // synthesis attribute PERIOD clk "50 MHz"
input rst_n;
input data_ready;
input [7:0] rx_data;
output lcd_rs;
output lcd_rw;
output lcd_e;
output lcd_7;
output lcd_6;
output lcd_5;
output lcd_4;

reg lcd_e, lcd_rs, lcd_rw, lcd_7, lcd_6, lcd_5, lcd_4;

reg [k+8:0] count;
reg [6:0] lcd_code;
reg [2:0] state;
reg [2:0] next_state;

wire lcd_ready = (state==1);

// store rx_data locally
reg [7:0] lcd_dataReg;
always @(posedge clk) if(data_ready & lcd_ready) lcd_dataReg <= rx_data;
wire [7:0] lcd_dataD = register_input ? lcd_dataReg : rx_data;

// continuous assignment by default of wire type, clr key clears display
wire clear = (rx_data == clr)? 1:0;
//assign {lcd_e,lcd_rs,lcd_rw,lcd_7,lcd_6,lcd_5,lcd_4} = lcd_code;

// sequential logic
always @ (posedge clk or negedge rst_n)
begin
if(~rst_n)
begin
state <= 0;
next_state <= 0;
count <= 0;
lcd_code[6:0] <= 0;
end
else
state <= next_state;
end

always @ (posedge clk)
begin
case (state)
3'b000: count <= count + 1;
3'b001: count <= 0;
3'b010: count <= (count[4]? 0 : count + 1);
3'b011: count <= (count[5]? 0 : count + 1);
3'b100: count <= (count[4]? 0 : count + 1);
3'b101: count <= (count[10]? 0 : count + 1);
3'b110: count <= count + 1;
endcase
{lcd_e,lcd_rs,lcd_rw,lcd_7,lcd_6,lcd_5,lcd_4} <= lcd_code;
if(state == 0 || state == 6) lcd_e <= ^count[k+1:k];
end // sequential logic

// combinatorial logic
always @ (state or count or data_ready or clear) begin
case(state)
3'b000:
begin
if(count[k+5:k+2] == 12)
next_state = 3'b1; // idle_data/1
else
next_state = 0;
end
3'b001:
begin
if(data_ready) begin
if(clear)
next_state = 3'b110; // clear/6
else
next_state = 3'b10; // disp_hn/2
end
else
next_state = 3'b1; // idle_data/1
end
3'b010:
begin
if(count[4])
next_state = 3'b11; // idle_high/3
else
next_state = 3'b10; // disp_hn/3
end
3'b011:
begin
if(count[5])
next_state = 3'b100; // disp_ln/4
else
next_state = 3'b11; // idle_high/3
end
3'b100:
begin
if(count[4])
next_state = 3'b101; // wait/5
else
next_state = 3'b100; // disp_ln/4
end
3'b101:
begin
if(count[10])
next_state = 3'b1; // idle_data/1
else
next_state = 3'b101; // wait/5
end
3'b110:
begin
if(count[k+3:k+2] == 2)
next_state = 3'h1; // idle_data/1
else
next_state = 3'h6; // clear/6
end
endcase
end // combinatorial logic

// output logic
always @(state or count or lcd_dataD) begin
lcd_code <= 7'h00;
case(state)
3'b000:
begin
case (count[k+5:k+2])
0: lcd_code <= 7'h43; // power-on initialization
1: lcd_code <= 7'h43;
2: lcd_code <= 7'h43;
3: lcd_code <= 7'h42;
4: lcd_code <= 7'h42; // function set
5: lcd_code <= 7'h48;
6: lcd_code <= 7'h40; // entry mode set
7: lcd_code <= 7'h46;
8: lcd_code <= 7'h40; // display on/off control
9: lcd_code <= 7'h4C;
10: lcd_code <= 7'h40; // display clear
11: lcd_code <= 7'h41;
endcase
end
3'b001:
lcd_code <= 7'h00;
3'b010:
lcd_code <= {3'b110, lcd_dataD[7:4]};
3'b011:
lcd_code <= 7'b0110000;
3'b100:
lcd_code <= {3'b110, lcd_dataD[3:0]};
3'b101:
lcd_code <= 7'b0110000;
3'b110:
begin
case(count[k+2])
0: lcd_code <= 7'h40; // display clear
1: lcd_code <= 7'h41;
endcase
end
endcase
end // output logic

endmodule



Tuesday, April 01, 2008

Linux Networking 3: network bridge and bump in the wire

A Linux network bridge can be understood as a bump in the wire on steroid. In the physical world, a bridge is used to connect multiple landmass together. This notion is used in a similar meaning in networking. A Linux network bridge is virtual and it connects different 'Ethernet' network segments together, albeit transparently to the Ethernet packets going through it.

Ever wondered what the 'Bridged' networking means in VMWare? It's exactly the kind of network setup allowed by Linux network bridge (practically handled by bridge-utils). Except that VMWare has its own implementation of a virtual network bridge that connects the guest virtual network and the host network together, thus allowing the guest OS virtual network direct access to the external (relative to the host) network.

Because bridge works at Layer 2 for Ethernet packets, a bridge can often be considered functionally equivalent to a switch, albeit a virtual software solution. The simplest bridge acts as a bump in the wire, connecting different network segments just like a switch. However, bridge has the following distinctive advantages:

1) A bridge can act as a network interface and assume a binding IP address, allowing network access to the Linux host.

2) Network packets going through a bridge can be manipulated by iptables, thus allowing greater control such as mangling and filtering not present in switch and bump in the wire.

Because a virtual bridge only examines Ethernet header (layer 2), it's transparent to IP protocols . This has some implications:

1) It's important to take care of ARP tables that translate Ethernet address to IP address, no arp poisoning or other monkey business. The Linux host must forward arp packets properly.

2) It's important to avoid routing loops (cyclic routes through bridges), often requiring turning Spanning Tree Protocol (STP) in network bridges.

A bridge is most useful in the following scenarios:

1) Network transparency and redundancy is required for internal network users. Redundant virtual network bridges can be set up (use STP if necessary) to allow non-interrupted network traffic flow.

2) Administrator needs better packet filtering control over packets striding over network segments.

3) Simply replacing a hardware switch or act as a bump in the wire (connecting two hosts on same network for example)

References:
1) http://www.linux-foundation.org/en/Net:Bridge
2) http://www.vmweekly.com/articles/networking_in_vmware/1/

Monday, March 10, 2008

Linux Networking 2: a router with port forwarding

Make simple things simple, complex things possible. Linux router is an example of this motto. A linux box with 2 NICs (network interface card) can function as a router with 2 simple commands from default configuration, and a 3rd command enables port forwarding to a specific port on a specific host. We'll cover a lot of theory of linux routing and firewalling in this article because subsequent article in this mini-serie are built based on the knowledge present here and will focus on more practical use.

First of all, let's understand the requirement of a router or its definition. A router routes network packets between two network segments. It needs to do source NAT or destination NAT on a network packet. NAT stands for network address translation and is a layer 3 (IP) functionality. What this means is that an outgoing network packet through the router will have its source IP address modified to the external IP of the router (sometimes referred to as WAN IP). A related incoming network packet or port forwarded network packet will have its destination IP address modified, known as destination NAT.

On 2.4+ Linux, NAT is done by iptables nat table during prerouting or postrouting. SNAT of an outgoing packet is performed during postrouting in nat just before it leaves the box. Linux kernel routing table knows that a packet destined to external IP address should go through the PREROUTING->FORWARD->POSTROUTING chain. Similarly, DNAT is performed during prerouting in nat just after it enters the box, typically going through PREROUTING->FORWARD->POSTROUTING chain. DNAT is done automatically for related or established packets (e.g. consequence of an outgoing SNAT SYN packet that establishes a network connection). DNAT is also done explicitly for packets that meet predefined port forwarding rules (an incoming SYN packet). It's strongly recommended the table traverse graph studied and understood.

By default, kernel disables forward chain. That is when a packet coming in on a NI (network interface) has a different destination IP address than the address bound to that NI will be dropped. To allow linux kernel to make routing decision on such kind of packets, the forward chain must be enabled. Next to ensure the kernel can properly route such kind of packets, DNAT must be performed such that when the packet is inspected by the kernel, upon consulting the kernel routing table, the packet can be forwarded to the correct destination NI.

An example will make this clear, given the following defintion

eth0_ip="192.168.0.1"
eth0_nw="192.168.0.1/24"
eth0_gw="192.168.0.150"
eth1_ip="192.168.1.1"
eth1_nw="192.168.1.1/24"
eth1_gw="192.168.1.150"
pfw_serv_ip="192.168.1.3"

kernel routing table can be displayed by "ip route" or "route -n", "ip route" shows more information and sometimes shows information not available through "route -n".

In this hypothetical case, let's suppose:
$eth0_nw route to eth0 via $eth0_nw_gw
$eth1_nw route to eth1 via $eth1_nw_gw
default route to eth0 via $eth0_nw_gw

This is equivalent in English, packets destined to $eth0_nw will be routed to interface eth0, ditto for $eth1_nw and eth1. And if a packet whose destination is not in either $eth0_nw or $eth1_nw, it should be routed to interface eth0.

Now that we have established the routing table and have the forward chain enabled (echo 1 > /proc/net/ipv4/ip_forward), let's see what happens when a packet originated from $pfw_server_ip with its destination ip set to kernel.org comes in from eth1. First the packet is seen on the wire and by the card, the kernel takes the packet and put it on the network stack. Before routing decision is made for this particular packet, there are 2 state machine states it will go through: the mangle table and nat table in PREROUTING chain. Two common actions will be taken by the kernel

1. The incoming packet has SYN flag set and is the first packet for an outgoing connection (similarly for UDP packet, the connection tracking is based on the 5-tuple: src ip, src port, dst ip, dst port, and protocol). The kernel consults the mangle table and nat table for PREROUTING chain and make appropriate changes to the packet. It's not recommended to do any filtering (ACCEPT, DROP, REJECT etc) with mangle/nat tables in PREROUTING chain. Suppose a DNAT rule exists to change the destination address of this packet in nat table, this packet will be redirected to a different server IP address. Thus it's extremely easy to construct a layer 3 proxy with Linux, some times referred to as port forwarding.

The mangle table has rules to modify the packet in other packet header fields different than the IP address. By marking the packet, mangle table can be used to select routing decisions for this packet based 'ip route/rule' kernel tables. For example, the mangle table rule can be used to create a tunnel, a bridge of 2 NIs. mangle table marks a packet and then the kernel routing table routes the packet based on its marking. We'll cover this in a later article in this serie.

2. The incoming packet does not have SYN flag set and the kernel connection tracking module determines it's part of an established connection. In this case, the rules that applied to the SYN packet of this 5-tuple connection are automatically applied to this packet as well.

At this point the packet leaves the PREROUTING chain, based on the kernel routing table, a routing decision will be made where this packet will be delivered to, typically one of the following decisions is made:

1. the destination ip address is one of local host addresses, in this case, the packet is delivered to the internal/local ip address and NI the address is bound to. Next the packet is scheduled to go through the INPUT/OUTPUT chain and the filter table. The filter table is the default table for the INPUT/OUTPUT chain, provided through iptables syntactical sugar. This is an often overlooked fact and causes most confusion to iptables beginners. It'd have been better that '-t filter' be made explicit on command line at the cost of increased verbosity.

It's possible a local process on the local host will consume the incoming packet after the INPUT chain and the story of the packet ends here.

2. the destination ip address is an external address, a routing table entry is available to calculate its destination network interface on the host, the packet is scheduled to go through the FORWARD chain next.

3. the destination ip address is an external address but none of the routing table entry yields a destination network interface on the host, this packet will be dropped. This packet is said to be undeliverable.

After the packet has gone through either the INPUT/OUTPUT or the FORWARD chain, another routing decision is made whether the packet is 'undeliverable' or can be sent out through POSTROUTING chain. Here is place to do either SNAT or MASQUERADE on the outgoing packets before it goes on the wire. The difference between SNAT or MASQUERADE is that MASQUERADE allows dynamic destination address calculation and is typically used when the outgoing NIC has its address obtained from a DHCP server. SNAT rule binds a static IP address to the nat table rule. If you are not sure you should use SNAT or MASQUERADE, use MASQUERADE just to be safe.

After the packet is mangled or SNATed/MASQUERADEd in POSTROUTING chain, it leaves the local host and is sent on the wire.

References:
1. http://iptables-tutorial.frozentux.net/images/tables_traverse.jpg
2. http://iptables-tutorial.frozentux.net/iptables-tutorial.html

Saturday, March 08, 2008

Linux Networking 1: server work load balancing with multiple NICs

We'll cover some advanced use of linux networking capabilities in this mini series (including load balancings, 2 nic with same IP--bonding, bridge, and router). We'll begin with load balancing of server workload. Although this discussion does not cover subjects such as routing, packet manipulation (through iptables), it illustrates from an application level, how to use a linux box with multiple NICs to do useful things. A linux box with multiple NICs will be a common theme of this mini series.

The concept of server work load balancing is to allow a linux box to use multiple NIC to service network traffic. A simple setup is to have a single external IP exposed to clients. Behind the external IP are multiple NICs that can form a dispatch table based on traffic and workload behind each NIC.

Let's use 2 NIC load balancing to illustrate the idea:

ext_nic(ip)-----load-balancer-demon-----NIC0-----SERVER0
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+----NIC1-----SERVER1

Whenever a client request comes in, the load-balancer-demon queries the SERVER behind a NIC to figure out which NIC the traffic/request should be forwarded to depending on the current workload on each server.

Thus the load-balancer-demon is a user space application that proxies client requests.

FPGA: Initial impression of Xilinx-3A starter board and fpga

I've recently started to learn FPGA architecture and Verilog hardware programming. It feels like the old DOS days when we could program interrupts and use 'outp' to signal hardware ports directly. In fact, the module port and pin assignment reminds me of the same pattern of hardware programming. The board has a builtin clock (oscillator) and with behavioral modelling, programer can program the hardware behavior. With DOS, I remember interrupt 8 was the XT8086 oscillator(timer) interrupt and the interrupt service code was executed at a fixed frequency. DOS allows programmer to reprogram the interrupt service code to emulate multitasking system.

FPGA is a powerful and flexible platform that supports many IO ports and levels of programming models (switch-level, gate-level, dataflow-level, and behavioral-level). Behavioral level programming is reminiscent of C programming except that Verilog provides concurrent and non-blocking (asynchronous) programming paradigms with native language contructs. For example, the always, initial procedual blocks are concurrent and the code sequence in these blocks are executed concurrently on fpga hardware. Verilog also provides delayed assignment, a nice variation of synchronous assignment. Nonblocking procedual assignment allows programer to describe asynchronous assignment behavior.

Programmable digital circuit is an interesting idea and hopefully I will have some interesting stuff to report later with the semi-expensive fpga development board.