-
Notifications
You must be signed in to change notification settings - Fork 0
/
magic_memory_dual_port.sv
113 lines (94 loc) · 2.36 KB
/
magic_memory_dual_port.sv
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
/*
* Dual-port magic memory
*
* Usage note: Avoid writing to the same address on both ports simultaneously.
*/
module magic_memory_dp
(
input clk,
/* Port A */
input read_a,
input write_a,
input [3:0] wmask_a,
input [31:0] address_a,
input [31:0] wdata_a,
output logic resp_a,
output logic [31:0] rdata_a,
/* Port B */
input read_b,
input write_b,
input [3:0] wmask_b,
input [31:0] address_b,
input [31:0] wdata_b,
output logic resp_b,
output logic [31:0] rdata_b
);
timeunit 1ns;
timeprecision 1ns;
logic [7:0] mem [2**(27)];
logic [26:0] internal_address_a;
logic [26:0] internal_address_b;
/* Initialize memory contents from memory.lst file */
initial
begin
$readmemh("memory.lst", mem);
end
/* Calculate internal address */
assign internal_address_a = address_a[26:0];
assign internal_address_b = address_b[26:0];
/* Read */
always_comb
begin : mem_read_a
rdata_a = {mem[internal_address_a+3], mem[internal_address_a+2], mem[internal_address_a+1], mem[internal_address_a]};
rdata_b = {mem[internal_address_b+3], mem[internal_address_b+2], mem[internal_address_b+1], mem[internal_address_b]};
end : mem_read_a
/* Port A write */
always @(posedge clk)
begin : mem_write_a
if (write_a)
begin
if (wmask_a[3])
begin
mem[internal_address_a+3] = wdata_a[31:24];
end
if (wmask_a[2])
begin
mem[internal_address_a+2] = wdata_a[23:16];
end
if (wmask_a[1])
begin
mem[internal_address_a+1] = wdata_a[15:8];
end
if (wmask_a[0])
begin
mem[internal_address_a] = wdata_a[7:0];
end
end
end : mem_write_a
/* Port B write */
always @(posedge clk)
begin : mem_write_b
if (write_b)
begin
if (wmask_b[3])
begin
mem[internal_address_b+3] = wdata_b[31:24];
end
if (wmask_b[2])
begin
mem[internal_address_b+2] = wdata_b[23:16];
end
if (wmask_b[1])
begin
mem[internal_address_b+1] = wdata_b[15:8];
end
if (wmask_b[0])
begin
mem[internal_address_b] = wdata_b[7:0];
end
end
end : mem_write_b
/* Magic memory responds immediately */
assign resp_a = read_a | write_a;
assign resp_b = read_b | write_b;
endmodule : magic_memory_dp