CPU.v 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840
  1. /*
  2. * B32P CPU
  3. */
  4. /* Features:
  5. - 5 stage pipeline
  6. - fetch FE (1)
  7. - decode DE (2)
  8. - execute EX (3)
  9. - memory MEM (4)
  10. - write back WB (5)
  11. - Hazard detection:
  12. - flush
  13. - stall (MEM to reg)
  14. - forward
  15. - Extendable amount of interrupts
  16. - higher priority for lower interrupt numbers
  17. - Variable delay support from InstrMem and DataMem:
  18. - NOTE/BUG: the instruction after a READ or WRITE was skipped if there is a DataMem delay but no InstrMem delay
  19. This might still be a problem when caching is implemented
  20. */
  21. module CPU(
  22. input clk, reset,
  23. output [26:0] bus_addr,
  24. output [31:0] bus_data,
  25. output bus_we,
  26. output bus_start,
  27. input [31:0] bus_q,
  28. input bus_done,
  29. input int1, int2, int3, int4, int5, int6, int7, int8, int9, int10,
  30. output reg led
  31. );
  32. parameter PCstart = 27'h000000; // internal SRAM addr 0 //27'h000000;
  33. parameter PCinterruptValidFrom = 27'd100; // interrupt valid after address 100
  34. parameter PCincrease = 1'b1; // number of addresses to increase the PC with after each instruction
  35. parameter InterruptJumpAddr = 27'd1;
  36. /*
  37. * CPU BUS
  38. */
  39. wire [31:0] arbiter_q;
  40. wire [31:0] addr_a;
  41. wire [31:0] data_a;
  42. wire we_a;
  43. wire start_a;
  44. wire done_a;
  45. wire [31:0] addr_b;
  46. wire [31:0] data_b;
  47. wire we_b;
  48. wire start_b;
  49. wire done_b;
  50. wire [26:0] arbiter_bus_addr; // bus_addr
  51. wire [31:0] arbiter_bus_data; // bus_data
  52. wire arbiter_bus_we; // bus_we
  53. wire arbiter_bus_start; // bus_start
  54. wire [31:0] arbiter_bus_q; // bus_q
  55. wire arbiter_bus_done; // bus_done
  56. // bus splitter
  57. assign bus_addr = arbiter_bus_addr;
  58. assign bus_data = arbiter_bus_data;
  59. assign bus_we = arbiter_bus_we;
  60. assign bus_start = arbiter_bus_start;
  61. assign arbiter_bus_q = bus_q;
  62. assign arbiter_bus_done = bus_done;
  63. Arbiter arbiter (
  64. .clk(clk),
  65. .reset(reset),
  66. // port a (Instr)
  67. .addr_a(addr_a),
  68. .data_a(data_a),
  69. .we_a(we_a),
  70. .start_a(start_a),
  71. .done_a(done_a),
  72. // port b (Data)
  73. .addr_b(addr_b),
  74. .data_b(data_b),
  75. .we_b(we_b),
  76. .start_b(start_b),
  77. .done_b(done_b),
  78. // output (both ports)
  79. .q(arbiter_q),
  80. // bus
  81. .bus_addr(arbiter_bus_addr),
  82. .bus_data(arbiter_bus_data),
  83. .bus_we(arbiter_bus_we),
  84. .bus_start(arbiter_bus_start),
  85. .bus_q(arbiter_bus_q),
  86. .bus_done(arbiter_bus_done)
  87. );
  88. /*
  89. * Interrupts
  90. */
  91. reg intDisabled = 1'b0;
  92. wire intCPU;
  93. wire [7:0] intID;
  94. IntController intController(
  95. .clk(clk),
  96. .reset(reset),
  97. .int1(int1),
  98. .int2(int2),
  99. .int3(int3),
  100. .int4(int4),
  101. .int5(int5),
  102. .int6(int6),
  103. .int7(int7),
  104. .int8(int8),
  105. .int9(int9),
  106. .int10(int10),
  107. .intDisabled(intDisabled),
  108. .intCPU(intCPU),
  109. .intID(intID)
  110. );
  111. // Registers for flush, stall and forwarding
  112. reg flush_FE, flush_DE, flush_EX, flush_MEM, flush_WB;
  113. reg stall_FE, stall_DE, stall_EX, stall_MEM, stall_WB;
  114. reg [1:0] forward_a, forward_b;
  115. // Cache delays
  116. wire instr_hit_FE;
  117. wire datamem_busy_MEM;
  118. /*
  119. * FETCH (FE)
  120. */
  121. // Program Counter, start at ROM[0]
  122. reg [31:0] pc_FE = PCstart;
  123. reg [31:0] pc_FE_backup = 32'd0;
  124. wire [31:0] pc4_FE;
  125. assign pc4_FE = pc_FE + 1'b1;
  126. wire [31:0] PC_backup_current;
  127. assign PC_backup_current = pc4_EX - PCincrease;
  128. // branch/jump/halt properly aligns interrupt with pipeline, as if it was a normal jump
  129. // this fixed all instability since the addition of caching (because this decreased the time to obtain instructions)
  130. assign interruptValid = (
  131. intCPU &&
  132. !intDisabled &&
  133. PC_backup_current >= PCinterruptValidFrom &&
  134. (
  135. branch_MEM || jumpr_MEM || jumpc_MEM || halt_MEM
  136. )
  137. );
  138. always @(posedge clk)
  139. begin
  140. if (reset)
  141. begin
  142. pc_FE <= PCstart;
  143. pc_FE_backup <= 32'd0;
  144. intDisabled <= 1'b0;
  145. end
  146. else
  147. begin
  148. // interrupt has highest priority
  149. if (interruptValid)
  150. begin
  151. intDisabled <= 1'b1;
  152. pc_FE_backup <= PC_backup_current;
  153. pc_FE <= InterruptJumpAddr;
  154. end
  155. else if (reti_MEM)
  156. begin
  157. intDisabled <= 1'b0;
  158. pc_FE <= pc_FE_backup;
  159. end
  160. // jump has priority over instruction cache stalls
  161. else if (jumpc_MEM || jumpr_MEM || halt_MEM || (branch_MEM && branch_passed_MEM))
  162. begin
  163. pc_FE <= jump_addr_MEM;
  164. end
  165. else if (stall_FE || (!instr_hit_FE) )
  166. begin
  167. pc_FE <= pc_FE;
  168. end
  169. else
  170. begin
  171. pc_FE <= pc4_FE;
  172. end
  173. end
  174. end
  175. // Instruction Memory
  176. // should eventually become a memory with variable latency
  177. // writes directly to next stage
  178. wire [31:0] instr_DE;
  179. InstrMem instrMem(
  180. .clk(clk),
  181. .reset(reset),
  182. .addr(pc_FE),
  183. .q(instr_DE),
  184. .hit(instr_hit_FE),
  185. // bus
  186. .bus_addr(addr_a),
  187. .bus_data(data_a),
  188. .bus_we(we_a),
  189. .bus_start(start_a),
  190. .bus_q(arbiter_q),
  191. .bus_done(done_a),
  192. .hold(stall_FE),
  193. .clear(flush_FE)
  194. );
  195. // Pass data from FE to DE
  196. wire [31:0] pc4_DE;
  197. Regr #(.N(32)) regr_pc4_FE_DE(
  198. .clk(clk),
  199. .hold(stall_FE),
  200. .clear(reset||flush_FE),
  201. .in(pc4_FE),
  202. .out(pc4_DE)
  203. );
  204. /*
  205. * DECODE (DE)
  206. */
  207. // Instruction Decoder
  208. wire [3:0] areg_DE, breg_DE, instrOP_DE;
  209. wire he_DE, oe_DE, sig_DE;
  210. InstructionDecoder instrDec_DE(
  211. .instr(instr_DE),
  212. .instrOP(instrOP_DE),
  213. .aluOP(),
  214. .constAlu(),
  215. .const16(),
  216. .const27(),
  217. .areg(areg_DE),
  218. .breg(breg_DE),
  219. .dreg(),
  220. .he(he_DE),
  221. .oe(oe_DE),
  222. .sig(sig_DE)
  223. );
  224. // Control Unit
  225. wire alu_use_const_DE;
  226. wire push_DE, pop_DE;
  227. wire dreg_we_DE;
  228. wire mem_write_DE, mem_read_DE;
  229. wire jumpc_DE, jumpr_DE, branch_DE, halt_DE, reti_DE, clearCache_DE;
  230. wire getIntID_DE, getPC_DE;
  231. ControlUnit controlUnit(
  232. // in
  233. .instrOP (instrOP_DE),
  234. .he (he_DE),
  235. // out
  236. .alu_use_const (alu_use_const_DE),
  237. .push (push_DE),
  238. .pop (pop_DE),
  239. .dreg_we (dreg_we_DE),
  240. .mem_write (mem_write_DE),
  241. .mem_read (mem_read_DE),
  242. .jumpc (jumpc_DE),
  243. .jumpr (jumpr_DE),
  244. .halt (halt_DE),
  245. .reti (reti_DE),
  246. .branch (branch_DE),
  247. .getIntID (getIntID_DE),
  248. .getPC (getPC_DE),
  249. .clearCache (clearCache_DE)
  250. );
  251. // Register Bank
  252. // writes directly to next stage
  253. wire [31:0] data_a_EX, data_b_EX;
  254. wire [3:0] dreg_WB;
  255. wire dreg_we_WB;
  256. reg [31:0] data_d_WB;
  257. Regbank regbank(
  258. .clk(clk),
  259. .reset(reset),
  260. .addr_a(areg_DE),
  261. .addr_b(breg_DE),
  262. .data_a(data_a_EX),
  263. .data_b(data_b_EX),
  264. // from WB stage
  265. .addr_d(dreg_WB),
  266. .data_d(data_d_WB),
  267. .we(dreg_we_WB),
  268. .hold(stall_DE),
  269. .clear(flush_DE)
  270. );
  271. // Pass data from DE to EX
  272. // Set to 0 during stall (bubble)
  273. wire [31:0] instr_EX;
  274. Regr #(.N(32)) regr_instr_DE_EX(
  275. .clk(clk),
  276. .hold(stall_DE),
  277. .clear(reset||flush_DE || stall_DE),
  278. .in(instr_DE),
  279. .out(instr_EX)
  280. );
  281. wire [31:0] pc4_EX;
  282. Regr #(.N(32)) regr_pc4_DE_EX(
  283. .clk(clk),
  284. .hold(stall_DE),
  285. .clear(reset||flush_DE),
  286. .in(pc4_DE),
  287. .out(pc4_EX)
  288. );
  289. // Set to 0 during stall (bubble)
  290. wire alu_use_const_EX;
  291. wire push_EX, pop_EX;
  292. wire dreg_we_EX;
  293. wire mem_write_EX, mem_read_EX;
  294. wire jumpc_EX, jumpr_EX, halt_EX, reti_EX, branch_EX, clearCache_EX;
  295. wire getIntID_EX, getPC_EX;
  296. Regr #(.N(14)) regr_cuflags_DE_EX(
  297. .clk (clk),
  298. .hold (stall_DE),
  299. .clear (reset||flush_DE || stall_DE),
  300. .in ({alu_use_const_DE, push_DE, pop_DE, dreg_we_DE, mem_write_DE, mem_read_DE, jumpc_DE, jumpr_DE, halt_DE, reti_DE, branch_DE, getIntID_DE, getPC_DE, clearCache_DE}),
  301. .out ({alu_use_const_EX, push_EX, pop_EX, dreg_we_EX, mem_write_EX, mem_read_EX, jumpc_EX, jumpr_EX, halt_EX, reti_EX, branch_EX, getIntID_EX, getPC_EX, clearCache_EX})
  302. );
  303. /*
  304. * EXECUTE (EX)
  305. */
  306. // Instruction Decoder
  307. wire [31:0] alu_const16_EX, alu_const16u_EX;
  308. wire [3:0] aluOP_EX;
  309. wire [3:0] areg_EX, breg_EX, dreg_EX;
  310. InstructionDecoder instrDec_EX(
  311. .instr(instr_EX),
  312. .instrOP(),
  313. .aluOP(aluOP_EX),
  314. .constAlu(alu_const16_EX),
  315. .constAluu(alu_const16u_EX),
  316. .const16(),
  317. .const27(),
  318. .areg(areg_EX),
  319. .breg(breg_EX),
  320. .dreg(dreg_EX),
  321. .he(),
  322. .oe(),
  323. .sig()
  324. );
  325. // ALU
  326. wire [31:0] alu_result_EX;
  327. // select constant or register for input b
  328. wire[31:0] alu_input_b_EX;
  329. assign alu_input_b_EX = (alu_use_const_EX && aluOP_EX[3:1] == 3'b110) ? alu_const16u_EX : // unsigned const for load(hi) instruction
  330. (alu_use_const_EX) ? alu_const16_EX :
  331. data_b_EX;
  332. // if forwarding, select forwarded data instead for input a of ALU
  333. reg [31:0] fw_data_a_EX;
  334. always @(*)
  335. begin
  336. case (forward_a)
  337. 2'd1: fw_data_a_EX <= alu_result_MEM;
  338. 2'd2: fw_data_a_EX <= data_d_WB;
  339. default: fw_data_a_EX <= data_a_EX;
  340. endcase
  341. end
  342. // if forwarding, select forwarded data instead for input b of ALU
  343. reg [31:0] fw_data_b_EX;
  344. always @(*)
  345. begin
  346. case (forward_b)
  347. 2'd1: fw_data_b_EX <= alu_result_MEM;
  348. 2'd2: fw_data_b_EX <= data_d_WB;
  349. default: fw_data_b_EX <= alu_input_b_EX;
  350. endcase
  351. end
  352. ALU alu(
  353. .opcode(aluOP_EX),
  354. .a(fw_data_a_EX),
  355. .b(fw_data_b_EX),
  356. .y(alu_result_EX)
  357. );
  358. // for special instructions, pass other data than alu result
  359. wire [31:0] execute_result_EX;
  360. assign execute_result_EX = (getPC_EX) ? pc4_EX - 1'b1:
  361. (getIntID_EX) ? intID:
  362. alu_result_EX;
  363. // Pass data from EX to MEM
  364. wire [31:0] instr_MEM;
  365. Regr #(.N(32)) regr_instr_EX_MEM(
  366. .clk(clk),
  367. .hold(stall_EX),
  368. .clear(reset||flush_EX),
  369. .in(instr_EX),
  370. .out(instr_MEM)
  371. );
  372. wire [31:0] data_a_MEM, data_b_MEM;
  373. Regr #(.N(64)) regr_regdata_EX_MEM(
  374. .clk(clk),
  375. .hold(stall_EX),
  376. .clear(reset||flush_EX),
  377. .in({fw_data_a_EX, fw_data_b_EX}), // forwarded data
  378. .out({data_a_MEM, data_b_MEM})
  379. );
  380. wire [31:0] pc4_MEM;
  381. Regr #(.N(32)) regr_pc4_EX_MEM(
  382. .clk(clk),
  383. .hold(stall_EX),
  384. .clear(reset||flush_EX),
  385. .in(pc4_EX),
  386. .out(pc4_MEM)
  387. );
  388. wire push_MEM, pop_MEM;
  389. wire dreg_we_MEM;
  390. wire mem_write_MEM, mem_read_MEM;
  391. wire jumpc_MEM, jumpr_MEM, halt_MEM, reti_MEM, branch_MEM, clearCache_MEM;
  392. Regr #(.N(11)) regr_cuflags_EX_MEM(
  393. .clk (clk),
  394. .hold (stall_EX),
  395. .clear (reset||flush_EX),
  396. .in ({push_EX, pop_EX, dreg_we_EX, mem_write_EX, mem_read_EX, jumpc_EX, jumpr_EX, halt_EX, reti_EX, branch_EX, clearCache_EX}),
  397. .out ({push_MEM, pop_MEM, dreg_we_MEM, mem_write_MEM, mem_read_MEM, jumpc_MEM, jumpr_MEM, halt_MEM, reti_MEM, branch_MEM, clearCache_MEM})
  398. );
  399. wire [31:0] alu_result_MEM;
  400. Regr #(.N(32)) regr_alu_result_EX_MEM(
  401. .clk(clk),
  402. .hold(stall_EX),
  403. .clear(reset||flush_EX),
  404. .in(execute_result_EX), // other data in case of special instructions
  405. .out(alu_result_MEM)
  406. );
  407. /*
  408. * MEMORY (MEM)
  409. */
  410. // Instruction Decoder
  411. wire [31:0] const16_MEM;
  412. wire [26:0] const27_MEM;
  413. wire [2:0] branchOP_MEM;
  414. wire oe_MEM, sig_MEM;
  415. wire [3:0] dreg_MEM;
  416. InstructionDecoder instrDec_MEM(
  417. .instr(instr_MEM),
  418. .instrOP(),
  419. .aluOP(),
  420. .branchOP(branchOP_MEM),
  421. .constAlu(),
  422. .const16(const16_MEM),
  423. .const27(const27_MEM),
  424. .areg(),
  425. .breg(),
  426. .dreg(dreg_MEM),
  427. .he(),
  428. .oe(oe_MEM),
  429. .sig(sig_MEM)
  430. );
  431. reg [31:0] jump_addr_MEM;
  432. always @(*)
  433. begin
  434. jump_addr_MEM <= 32'd0;
  435. if (jumpc_MEM)
  436. begin
  437. if (oe_MEM)
  438. begin
  439. // add sign extended to allow negative offsets
  440. jump_addr_MEM <= (pc4_MEM - 1'b1) + {{5{const27_MEM[26]}}, const27_MEM[26:0]};
  441. end
  442. else
  443. begin
  444. jump_addr_MEM <= {5'd0, const27_MEM};
  445. end
  446. end
  447. else if (jumpr_MEM)
  448. begin
  449. if (oe_MEM)
  450. begin
  451. jump_addr_MEM <= (pc4_MEM - 1'b1) + (data_b_MEM + const16_MEM);
  452. end
  453. else
  454. begin
  455. jump_addr_MEM <= data_b_MEM + const16_MEM;
  456. end
  457. end
  458. else if (branch_MEM)
  459. begin
  460. jump_addr_MEM <= (pc4_MEM - 1'b1) + const16_MEM;
  461. end
  462. else if (halt_MEM)
  463. begin
  464. // jump to same address to keep halting
  465. jump_addr_MEM <= pc4_MEM - 1'b1;
  466. end
  467. end
  468. // Opcodes
  469. localparam
  470. BRANCH_OP_BEQ = 3'b000, // A == B
  471. BRANCH_OP_BGT = 3'b001, // A > B
  472. BRANCH_OP_BGE = 3'b010, // A >= B
  473. BRANCH_OP_U1 = 3'b011, // Unimplemented 1
  474. BRANCH_OP_BNE = 3'b100, // A != B
  475. BRANCH_OP_BLT = 3'b101, // A < B
  476. BRANCH_OP_BLE = 3'b110, // A <= B
  477. BRANCH_OP_U2 = 3'b111; // Unimplemented 2
  478. reg branch_passed_MEM;
  479. always @(*)
  480. begin
  481. branch_passed_MEM <= 1'b0;
  482. case (branchOP_MEM)
  483. BRANCH_OP_BEQ:
  484. begin
  485. branch_passed_MEM <= (data_a_MEM == data_b_MEM);
  486. end
  487. BRANCH_OP_BGT:
  488. begin
  489. branch_passed_MEM <= (sig_MEM) ? ($signed(data_a_MEM) > $signed(data_b_MEM)) : (data_a_MEM > data_b_MEM);
  490. end
  491. BRANCH_OP_BGE:
  492. begin
  493. branch_passed_MEM <= (sig_MEM) ? ($signed(data_a_MEM) >= $signed(data_b_MEM)) : (data_a_MEM >= data_b_MEM);
  494. end
  495. BRANCH_OP_BNE:
  496. begin
  497. branch_passed_MEM <= (data_a_MEM != data_b_MEM);
  498. end
  499. BRANCH_OP_BLT:
  500. begin
  501. branch_passed_MEM <= (sig_MEM) ? ($signed(data_a_MEM) < $signed(data_b_MEM)) : (data_a_MEM < data_b_MEM);
  502. end
  503. BRANCH_OP_BLE:
  504. begin
  505. branch_passed_MEM <= (sig_MEM) ? ($signed(data_a_MEM) <= $signed(data_b_MEM)) : (data_a_MEM <= data_b_MEM);
  506. end
  507. endcase
  508. end
  509. // Data Memory
  510. // should eventually become a memory with variable latency
  511. // writes directly to the next stage
  512. wire [31:0] dataMem_q_WB;
  513. wire [31:0] dataMem_addr_MEM;
  514. assign dataMem_addr_MEM = data_a_MEM + const16_MEM;
  515. DataMem dataMem(
  516. .clk(clk),
  517. .reset(reset),
  518. .addr(dataMem_addr_MEM),
  519. .we(mem_write_MEM),
  520. .re(mem_read_MEM),
  521. .data(data_b_MEM),
  522. .q(dataMem_q_WB),
  523. .busy(datamem_busy_MEM),
  524. // bus
  525. .bus_addr(addr_b),
  526. .bus_data(data_b),
  527. .bus_we(we_b),
  528. .bus_start(start_b),
  529. .bus_q(arbiter_q),
  530. .bus_done(done_b),
  531. .hold(stall_MEM),
  532. .clear(flush_MEM)
  533. );
  534. // Stack
  535. // writes directly to the next stage
  536. wire [31:0] stack_q_WB;
  537. Stack stack(
  538. .clk(clk),
  539. .reset(reset),
  540. .q(stack_q_WB),
  541. .d(data_b_MEM),
  542. .push(push_MEM),
  543. .pop(pop_MEM),
  544. .hold(stall_MEM),
  545. .clear(flush_MEM)
  546. );
  547. // Pass data from MEM to WB
  548. wire [31:0] instr_WB;
  549. Regr #(.N(32)) regr_instr_MEM_WB(
  550. .clk(clk),
  551. .hold(stall_MEM),
  552. .clear(reset||flush_MEM),
  553. .in(instr_MEM),
  554. .out(instr_WB)
  555. );
  556. wire [31:0] alu_result_WB;
  557. Regr #(.N(32)) regr_alu_result_MEM_WB(
  558. .clk(clk),
  559. .hold(stall_MEM),
  560. .clear(reset||flush_MEM),
  561. .in(alu_result_MEM),
  562. .out(alu_result_WB)
  563. );
  564. wire [31:0] pc4_WB;
  565. Regr #(.N(32)) regr_pc4_MEM_WB(
  566. .clk(clk),
  567. .hold(stall_MEM),
  568. .clear(reset||flush_MEM),
  569. .in(pc4_MEM),
  570. .out(pc4_WB)
  571. );
  572. wire pop_WB, mem_read_WB;
  573. //wire dreg_we_WB;
  574. Regr #(.N(3)) regr_cuflags_MEM_WB(
  575. .clk (clk),
  576. .hold (stall_MEM),
  577. .clear (reset||flush_MEM),
  578. .in ({pop_MEM, dreg_we_MEM, mem_read_MEM}),
  579. .out ({pop_WB, dreg_we_WB, mem_read_WB})
  580. );
  581. /*
  582. * WRITE BACK (WB)
  583. */
  584. InstructionDecoder instrDec_WB(
  585. .instr(instr_WB),
  586. .instrOP(),
  587. .aluOP(),
  588. .constAlu(),
  589. .const16(),
  590. .const16u(),
  591. .const27(),
  592. .areg(),
  593. .breg(),
  594. .dreg(dreg_WB),
  595. .he(),
  596. .oe(),
  597. .sig()
  598. );
  599. always @(*)
  600. begin
  601. case (1'b1)
  602. pop_WB:
  603. begin
  604. data_d_WB <= stack_q_WB;
  605. end
  606. mem_read_WB:
  607. begin
  608. data_d_WB <= dataMem_q_WB;
  609. end
  610. default: // (ALU, savPC, IntID)
  611. begin
  612. data_d_WB <= alu_result_WB;
  613. end
  614. endcase
  615. end
  616. /*
  617. * FLUSH
  618. */
  619. always @(*)
  620. begin
  621. flush_FE <= 1'b0;
  622. flush_DE <= 1'b0;
  623. flush_EX <= 1'b0;
  624. flush_MEM <= 1'b0;
  625. flush_WB <= 1'b0;
  626. // flush on jumps or interrupts
  627. if (jumpc_MEM || jumpr_MEM || halt_MEM || (branch_MEM && branch_passed_MEM) || reti_MEM || interruptValid)
  628. begin
  629. flush_FE <= 1'b1;
  630. flush_DE <= 1'b1;
  631. flush_EX <= 1'b1;
  632. end
  633. // flush MEM when busy, causing a bubble
  634. if ((mem_read_MEM || mem_write_MEM) && datamem_busy_MEM)
  635. begin
  636. flush_MEM <= 1'b1;
  637. end
  638. end
  639. /*
  640. * STALL
  641. */
  642. always @(*)
  643. begin
  644. stall_FE <= 1'b0;
  645. stall_DE <= 1'b0;
  646. stall_EX <= 1'b0;
  647. stall_MEM <= 1'b0;
  648. stall_WB <= 1'b0;
  649. // stall if an instruction in EX uses the result of a some operation in MEM (dreg_mem)
  650. if ((mem_read_EX || pop_EX) && ( (dreg_EX == areg_DE) || (dreg_EX == breg_DE)) )
  651. begin
  652. stall_FE <= 1'b1;
  653. stall_DE <= 1'b1;
  654. end
  655. // stall if read or write in data MEM causes the busy flag to be set
  656. if ((mem_read_MEM || mem_write_MEM) && datamem_busy_MEM)
  657. begin
  658. stall_FE <= 1'b1;
  659. stall_DE <= 1'b1;
  660. stall_EX <= 1'b1;
  661. end
  662. end
  663. /*
  664. * FORWARDING
  665. */
  666. // MEM (4) -> EX (3)
  667. // WB (5) -> EX (3)
  668. always @(*)
  669. begin
  670. // input a of ALU
  671. forward_a <= 2'd0; // default to no forwarding
  672. if (dreg_we_MEM && (dreg_MEM == areg_EX) && (areg_EX != 4'd0))
  673. begin
  674. forward_a <= 2'd1; // priority 1: forward from MEM to EX
  675. end
  676. else if (dreg_we_WB && (dreg_WB == areg_EX) && (areg_EX != 4'd0))
  677. begin
  678. forward_a <= 2'd2; // priority 2: forward from WB to EX
  679. end
  680. // input b of ALU
  681. forward_b <= 2'd0; // default to no forwarding
  682. if (dreg_we_MEM && (dreg_MEM == breg_EX) && (breg_EX != 4'd0))
  683. begin
  684. forward_b <= 2'd1; // priority 1: forward from MEM to EX
  685. end
  686. else if (dreg_we_WB && (dreg_WB == breg_EX) && (breg_EX != 4'd0))
  687. begin
  688. forward_b <= 2'd2; // priority 2: forward from WB to EX
  689. end
  690. end
  691. always @(posedge clk)
  692. begin
  693. led <= (pc_FE != 27'd8);
  694. end
  695. endmodule