| 1 | /* |
| 2 | * Memory Harness with Wishbone Slave interface |
| 3 | * |
| 4 | * (C) Copyleft 2007 Simply RISC LLP |
| 5 | * AUTHOR: Fabrizio Fazzino <fabrizio.fazzino@srisc.com> |
| 6 | * |
| 7 | * LICENSE: |
| 8 | * This is a Free Hardware Design; you can redistribute it and/or |
| 9 | * modify it under the terms of the GNU General Public License |
| 10 | * version 2 as published by the Free Software Foundation. |
| 11 | * The above named program is distributed in the hope that it will |
| 12 | * be useful, but WITHOUT ANY WARRANTY; without even the implied |
| 13 | * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
| 14 | * See the GNU General Public License for more details. |
| 15 | * |
| 16 | * DESCRIPTION: |
| 17 | * Filename is a parameter, and the corresponding file content |
| 18 | * must follow the rules stated in Verilog standard for the |
| 19 | * $readmemh() system task. |
| 20 | * For instance if you don't change the default name you just |
| 21 | * have to put a text file named "memory.hex" in your simulation |
| 22 | * directory with the following content inside: |
| 23 | * |
| 24 | * // We start from address zero by default: |
| 25 | * 1234567812345678 |
| 26 | * FEDCBA9876543210 |
| 27 | * // Now we jump to doubleword number 10 (i.e. address 80): |
| 28 | * @ 10 |
| 29 | * 02468ACE13579BDF |
| 30 | * |
| 31 | * This memory harness was originally based upon a Wishbone Slave |
| 32 | * model written by Rudolf Usselmann <rudi@asics.ws> but now I've |
| 33 | * written it again entirely from scratch. |
| 34 | */ |
| 35 | |
| 36 | |
| 37 | module mem_harness(sys_clock_i, sys_reset_i, wbs_addr_i, wbs_data_i, wbs_data_o, |
| 38 | wbs_cycle_i, wbs_strobe_i, wbs_sel_i, wbs_we_i, wbs_ack_o); |
| 39 | // syn black_box |
| 40 | parameter addr_bits = 24; |
| 41 | parameter addr_max = ((1 << addr_bits) - 1); |
| 42 | parameter memfilename = "memory.hex"; |
| 43 | parameter initmem = 0; |
| 44 | parameter loadmem = 1; |
| 45 | parameter memdefaultcontent = 64'b0; |
| 46 | input sys_clock_i; |
| 47 | input sys_reset_i; |
| 48 | input wbs_cycle_i; |
| 49 | input wbs_strobe_i; |
| 50 | input [63:0] wbs_addr_i; |
| 51 | input [63:0] wbs_data_i; |
| 52 | input wbs_we_i; |
| 53 | input [7:0] wbs_sel_i; |
| 54 | output wbs_ack_o; |
| 55 | output [63:0] wbs_data_o; |
| 56 | |
| 57 | reg wbs_ack_o; |
| 58 | reg [63:0] wbs_data_o; |
| 59 | reg /*sparse*/ |
| 60 | [63:0] mem[addr_max:0]; |
| 61 | wire [63:0] tmp_rd; |
| 62 | wire [63:0] tmp_wd; |
| 63 | integer i; |
| 64 | |
| 65 | |
| 66 | /* synthesis translate_off */ |
| 67 | initial begin |
| 68 | $display("INFO: MEMH %m: Memory Harness with Wishbone Slave interface starting..."); |
| 69 | $display("INFO: MEMH %m: %0d Address Bits / %0d Doublewords / %0d Bytes Total Memory", addr_bits, addr_max+1, (addr_max+1)*8); |
| 70 | $readmemh(memfilename, mem); |
| 71 | $display("INFO: MEMH %m: Memory initialization completed"); |
| 72 | end |
| 73 | |
| 74 | /* synthesis translate_on */ |
| 75 | |
| 76 | assign tmp_rd = mem[wbs_addr_i[(addr_bits + 2):3]]; |
| 77 | assign tmp_wd[63:56] = ((!wbs_sel_i[7]) ? tmp_rd[63:56] : |
| 78 | wbs_data_i[63:56]); |
| 79 | assign tmp_wd[55:48] = ((!wbs_sel_i[6]) ? tmp_rd[55:48] : |
| 80 | wbs_data_i[55:48]); |
| 81 | assign tmp_wd[47:40] = ((!wbs_sel_i[5]) ? tmp_rd[47:40] : |
| 82 | wbs_data_i[47:40]); |
| 83 | assign tmp_wd[39:32] = ((!wbs_sel_i[4]) ? tmp_rd[39:32] : |
| 84 | wbs_data_i[39:32]); |
| 85 | assign tmp_wd[31:24] = ((!wbs_sel_i[3]) ? tmp_rd[31:24] : |
| 86 | wbs_data_i[31:24]); |
| 87 | assign tmp_wd[23:16] = ((!wbs_sel_i[2]) ? tmp_rd[23:16] : |
| 88 | wbs_data_i[23:16]); |
| 89 | assign tmp_wd[15:8] = ((!wbs_sel_i[1]) ? tmp_rd[15:8] : wbs_data_i[15:8] |
| 90 | ); |
| 91 | assign tmp_wd[7:0] = ((!wbs_sel_i[0]) ? tmp_rd[7:0] : wbs_data_i[7:0]); |
| 92 | |
| 93 | always @(posedge sys_clock_i) begin |
| 94 | if ((wbs_cycle_i & wbs_strobe_i) & (!wbs_we_i)) begin |
| 95 | wbs_ack_o = 1; |
| 96 | wbs_data_o = tmp_rd; |
| 97 | end |
| 98 | else if ((wbs_cycle_i & wbs_strobe_i) & wbs_we_i) begin |
| 99 | wbs_ack_o = 1; |
| 100 | wbs_data_o = 64'hzzzzzzzzzzzzzzzz; |
| 101 | mem[wbs_addr_i[(addr_bits + 2):3]] = tmp_wd; |
| 102 | end |
| 103 | else |
| 104 | begin |
| 105 | wbs_ack_o = 0; |
| 106 | wbs_data_o = 64'hzzzzzzzzzzzzzzzz; |
| 107 | end |
| 108 | end |
| 109 | endmodule |