summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulian Blake Kongslie2021-03-28 16:32:13 -0700
committerJulian Blake Kongslie2021-03-28 16:32:13 -0700
commit9d5484923941eb393381b5769a4f1f66ff5df5ca (patch)
treee98b8d5eac2b1c0aa1a459ff741693a9d0e3d3d4
parentSome more interesting opcodes. (diff)
downloadnoncpu-9d5484923941eb393381b5769a4f1f66ff5df5ca.tar.xz
Use a separate memory module.
Hopefully this will infer a memory the way we want in Quartus.
Diffstat (limited to '')
-rw-r--r--hdl/mem.sv30
-rw-r--r--hdl/top.sv89
2 files changed, 110 insertions, 9 deletions
diff --git a/hdl/mem.sv b/hdl/mem.sv
new file mode 100644
index 0000000..906870d
--- /dev/null
+++ b/hdl/mem.sv
@@ -0,0 +1,30 @@
1module mem
2 ( input bit clk
3
4 , output bit ready
5 , input bit valid
6 , input bit write
7 , input bit [ADDR_BITS-1:0] address
8 , input bit [DATA_BITS-1:0] write_data
9 , output bit [DATA_BITS-1:0] read_data // Valid exactly the cycle after address is consumed.
10 );
11
12parameter ADDR_BITS;
13parameter DATA_BITS;
14parameter INIT_FILE;
15
16bit [DATA_BITS-1:0] storage [0:(1<<ADDR_BITS)-1];
17initial $readmemh(INIT_FILE, storage);
18
19assign ready = 1;
20
21always_ff @(posedge clk) begin
22 if (ready && valid) begin
23 if (write)
24 storage[address] <= write_data;
25 else
26 read_data <= storage[address];
27 end
28end
29
30endmodule
diff --git a/hdl/top.sv b/hdl/top.sv
index aa5a4e2..4f56b1f 100644
--- a/hdl/top.sv
+++ b/hdl/top.sv
@@ -13,8 +13,28 @@ bit have_reset = 0;
13always_ff @(posedge clk) if (reset) have_reset <= 1; 13always_ff @(posedge clk) if (reset) have_reset <= 1;
14assign reset = !reset_n || !have_reset; 14assign reset = !reset_n || !have_reset;
15 15
16bit [DATA_BITS-1:0] mem [0:(1<<ADDR_BITS)-1]; 16bit mem_ready; `define mem_ready `past(mem_ready)
17initial $readmemh("mem/mem.hex", mem); 17bit mem_valid;
18bit mem_write;
19bit [ADDR_BITS-1:0] mem_address;
20bit [DATA_BITS-1:0] mem_write_data;
21bit [DATA_BITS-1:0] mem_read_data;
22
23mem
24 #( .ADDR_BITS(ADDR_BITS)
25 , .DATA_BITS(DATA_BITS)
26 , .INIT_FILE("mem/mem.hex")
27 )
28 memory
29 ( .clk(clk)
30
31 , .ready(mem_ready)
32 , .valid(mem_valid)
33 , .address(mem_address)
34 , .write(mem_write)
35 , .write_data(mem_write_data)
36 , .read_data(mem_read_data)
37 );
18 38
19bit rx_ready; 39bit rx_ready;
20bit rx_valid; 40bit rx_valid;
@@ -48,10 +68,12 @@ bit [DATA_BITS-1:0] idx;
48enum 68enum
49 { FETCH 69 { FETCH
50 , DECODE 70 , DECODE
71 , MEMORY
51 } state; 72 } state;
52 73
53always_ff @(posedge clk) begin 74always_ff @(posedge clk) begin
54 if (reset) begin 75 if (reset) begin
76 mem_valid = 0;
55 rx_ready = 0; 77 rx_ready = 0;
56 tx_valid = 0; 78 tx_valid = 0;
57 tx_data = 0; 79 tx_data = 0;
@@ -60,22 +82,41 @@ always_ff @(posedge clk) begin
60 idx = 0; 82 idx = 0;
61 state = state.first; 83 state = state.first;
62 end else begin 84 end else begin
85 `ifdef DEBUG $display("s=%0d pc=%x (acc=%x idx=%x)", state, pc, acc, idx); `endif
63 if (`tx_ready) tx_valid = 0; 86 if (`tx_ready) tx_valid = 0;
64 87
65 case (state) 88 case (state)
66 FETCH: begin 89 FETCH: begin
67 {opcode, operand} = mem[{2'b0, pc}]; 90 `ifdef DEBUG $display("\tfetch"); `endif
68 ++pc; 91 mem_valid = 1;
69 state = DECODE; 92 mem_address = {2'b0, pc};
93 mem_write = 0;
94 if (`mem_ready) begin
95 state = DECODE;
96 ++pc;
97 end
70 end 98 end
71 99
72 DECODE: begin 100 DECODE: begin
73 //$display("%x %x:%x (acc=%x idx=%x)", pc, opcode, operand, acc, idx); 101 mem_valid = 0;
102 mem_write = 0;
74 state = FETCH; 103 state = FETCH;
104 {opcode, operand} = mem_read_data;
105 `ifdef DEBUG $display("\tdecode %x:%x", opcode, operand); `endif
75 case (opcode) 106 case (opcode)
76 'h0: acc = {{4{operand[7]}}, operand}; 107 'h0: acc = {{4{operand[7]}}, operand};
77 'h1: acc = mem[idx + operand]; 108 'h1: begin
78 'h2: mem[idx + operand] = acc; 109 mem_valid = 1;
110 mem_address = idx + operand;
111 state = MEMORY;
112 end
113 'h2: begin
114 mem_valid = 1;
115 mem_address = idx + operand;
116 mem_write = 1;
117 mem_write_data = acc;
118 if (! `mem_ready) state = MEMORY;
119 end
79 'h3: if (acc != operand) ++pc; 120 'h3: if (acc != operand) ++pc;
80 'h4: pc = pc + {{4{operand[7]}}, operand}; 121 'h4: pc = pc + {{4{operand[7]}}, operand};
81 'hf: begin 122 'hf: begin
@@ -87,7 +128,7 @@ always_ff @(posedge clk) begin
87 if (operand[5]) idx = acc; 128 if (operand[5]) idx = acc;
88 if (operand[6]) begin 129 if (operand[6]) begin
89 if (tx_valid) begin 130 if (tx_valid) begin
90 state = DECODE; 131 state = MEMORY;
91 end else begin 132 end else begin
92 tx_valid = 1; 133 tx_valid = 1;
93 tx_data = acc[7:0]; 134 tx_data = acc[7:0];
@@ -97,7 +138,37 @@ always_ff @(posedge clk) begin
97 end 138 end
98 endcase 139 endcase
99 end 140 end
141
142 MEMORY: begin
143 `ifdef DEBUG $display("\tstall"); `endif
144 if (`mem_ready) begin
145 mem_valid = 0;
146 mem_write = 0;
147 end
148 state = FETCH;
149 case (opcode)
150 'h1: begin
151 if (`mem_ready) begin
152 acc = mem_read_data;
153 end else begin
154 state = MEMORY;
155 end
156 end
157 'hf: begin
158 if (operand[6]) begin
159 if (tx_valid) begin
160 state = MEMORY;
161 end else begin
162 tx_valid = 1;
163 tx_data = acc[7:0];
164 end
165 end
166 end
167 endcase
168 end
100 endcase 169 endcase
170
171 `ifdef DEBUG if (mem_valid) $display("\tmem addr=%x w=%b", mem_address, mem_write); `endif
101 end 172 end
102end 173end
103 174