All targets must deal with their own firmware now
[yari.git] / Icarus / dpram.v
blobac11e76af560d01e60bf862c34619efcf9b3b496
1 `timescale 1 ns / 10 ps
2 module dpram (clock,
3 address_a, byteena_a, wrdata_a, wren_a, rddata_a,
4 address_b, byteena_b, wrdata_b, wren_b, rddata_b);
6 parameter DATA_WIDTH = 32;
7 parameter ADDR_WIDTH = 7;
8 parameter INIT_FILE = "somefile"; // No .mif!
9 parameter DEBUG = 0;
11 input clock;
13 input [ADDR_WIDTH-1:0] address_a;
14 input [DATA_WIDTH/8-1:0] byteena_a;
15 input [DATA_WIDTH-1:0] wrdata_a;
16 input wren_a;
17 output reg [DATA_WIDTH-1:0] rddata_a;
19 input [ADDR_WIDTH-1:0] address_b;
20 input [DATA_WIDTH-1:0] wrdata_b;
21 input [DATA_WIDTH/8-1:0] byteena_b;
22 input wren_b;
23 output reg [DATA_WIDTH-1:0] rddata_b;
25 // Declare the RAM variable
26 reg [DATA_WIDTH/4-1:0] ram0[(1 << ADDR_WIDTH)-1:0];
27 reg [DATA_WIDTH/4-1:0] ram1[(1 << ADDR_WIDTH)-1:0];
28 reg [DATA_WIDTH/4-1:0] ram2[(1 << ADDR_WIDTH)-1:0];
29 reg [DATA_WIDTH/4-1:0] ram3[(1 << ADDR_WIDTH)-1:0];
31 always @(posedge clock) begin
32 if (wren_a) begin
33 if (byteena_a[0]) ram0[address_a] <= wrdata_a[ 7: 0];
34 if (byteena_a[1]) ram1[address_a] <= wrdata_a[15: 8];
35 if (byteena_a[2]) ram2[address_a] <= wrdata_a[23:16];
36 if (byteena_a[3]) ram3[address_a] <= wrdata_a[31:24];
37 end
39 if (wren_b) begin
40 if (byteena_b[0]) ram0[address_b] <= wrdata_b[ 7: 0];
41 if (byteena_b[1]) ram1[address_b] <= wrdata_b[15: 8];
42 if (byteena_b[2]) ram2[address_b] <= wrdata_b[23:16];
43 if (byteena_b[3]) ram3[address_b] <= wrdata_b[31:24];
44 end
46 // Read (if read_addr == write_addr, return OLD data). To return
47 // NEW data, use = (blocking write) rather than <= (non-blocking write)
48 // in the write assignment. NOTE: NEW data may require extra bypass
49 // logic around the RAM.
50 rddata_a <= {ram3[address_a],ram2[address_a],ram1[address_a],ram0[address_a]};
51 rddata_b <= {ram3[address_b],ram2[address_b],ram1[address_b],ram0[address_b]};
53 if (DEBUG) begin
54 $display("%05d dram[%d] = %d", $time,
55 address_a,
56 {ram3[address_a],ram2[address_a],ram1[address_a],ram0[address_a]});
57 if (wren_a)
58 $display("%05d dram[%d] <-a %d/%d [%d/%d/%d]", $time,
59 address_a, wrdata_a, byteena_a, address_b, wren_b, byteena_b);
60 if (wren_b)
61 $display("%05d dram[%d] <-b %d/%d [%d/%d/%d]", $time,
62 address_b, wrdata_b, byteena_b, address_a, wren_a, byteena_a);
63 end
64 end
67 * This is so lame, but it looks like a Verilog limitation that we
68 * can't write
70 * if (byteena_b[3]) ram[address_b][31:24] <= wrdata_b[31:24];
72 * thus we have to manually split the ram into four blocks if we desire
73 * byte enables. Meh.
75 reg [DATA_WIDTH-1:0] ram_initial[(1 << ADDR_WIDTH)-1:0];
78 reg [31:0] i;
79 initial begin
80 #0 $readmemh({INIT_FILE,".data"}, ram_initial);
81 for (i = 0; i < 1 << ADDR_WIDTH; i = i + 1)
82 {ram3[i],ram2[i],ram1[i],ram0[i]} = ram_initial[i];
83 end
84 endmodule