CPU.v 17 KB

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