CPU.v 17 KB

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