To mitigate structural hazard in Register File, use separate read and write ports as the book says.
Now comes the problem of data collision...
how can we implement write in "first half" and read in "second half" of clock cycle?
As Dave hinted, this is something you don't have to worry about in RTL. It is actually hidden from RTL abstraction and rather implemented in the memory cells itself to avoid data collision due to simultaneous read and write to same address.
Suppose you want to implement Register File in Block RAM (True dual port) on FPGAs. In such cases you may want to ensure a timing delay between the read and write clock edges to avoid data collision. This timing requirement is usually given in the RAM datasheet itself.
As an example: I found a document from microsemi which you may find useful. It talks only about data collision (read-read, write-read, read-write, write-write) on dual port SRAMs on FPGAs, and how to time the read and write clock edges to avoid getting an unknown or 'X' value.
Data collision is inherent to memory cells like SRAM. Instead of RAM cells, you can simply implement Register File using flip-flops and muxes/decoders in RTL. You will find this implementation in most of the opensource RISC cores out there. Something like this:
Now, you don't have to worry about the problem of data collision as you can always read and write to a flip-flop on same clock edge. You will always read the 'older' value, provided that setup and hold timings are met.