datapath.sv 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  1. import risc8_pkg::*;
  2. import alu_pkg::*;
  3. module datapath8(
  4. input logic clk, rst, interrupt,
  5. risc8_cdi.datapath cdi,
  6. input word com_rd,
  7. input wire [23:0] immr,
  8. output word com_wr, com_addr,
  9. input [15:0] mem_rd,
  10. output [15:0] mem_wr,
  11. output reg [15:0] pc,
  12. output reg [23:0] mem_addr
  13. );
  14. // regiser file outputs
  15. word r1, r2;
  16. // immidate override
  17. word imo0, imo1, imo2;
  18. reg imo0_en, imo1_en, imo2_en, imo_en, imo_reg;
  19. reg [23:0] imm;
  20. always_comb begin
  21. imo_reg = imo0_en | imo1_en | imo2_en;
  22. imo_en = imo_reg & (cdi.imoctl == IMO_NONE);
  23. imm[7:0] = (imo_en & imo2_en) ? imo2 : immr[7:0];
  24. imm[15:8] = (imo_en & imo1_en) ? imo1 : immr[15:8];
  25. imm[23:16] = (imo_en & imo0_en) ? imo0 : immr[23:16];
  26. end
  27. always_ff@(posedge clk) begin
  28. if(imo_en | rst) begin
  29. imo0_en <= 0;
  30. imo1_en <= 0;
  31. imo2_en <= 0;
  32. end else case(cdi.imoctl)
  33. IMO_0: begin
  34. imo0 <= r1;
  35. imo0_en <= 1;
  36. end
  37. IMO_1: begin
  38. imo1 <= r1;
  39. imo1_en <= 1;
  40. end
  41. IMO_2: begin
  42. imo2 <= r1;
  43. imo2_en <= 1;
  44. end
  45. endcase
  46. end
  47. // ======================== //
  48. // ALU //
  49. // ======================== //
  50. word srcA, srcB, alu_rlo, alu_rhi, alu_rhit;
  51. logic cout, cinr, cin, alu_eq, alu_gt, alu_zero, alu_sign;
  52. assign cdi.alu_comp = {alu_eq, alu_gt, alu_zero};
  53. assign alu_sign = 0;
  54. assign cin = (cdi.aluf[0]) ? cinr : 0; // Enable carry in
  55. always_ff@(posedge clk) begin
  56. if(rst) begin
  57. cinr <= '0;
  58. alu_rhi <= '0;
  59. end else begin
  60. if((cdi.alu_op == ALU_ADD)|(cdi.alu_op == ALU_SUB))
  61. cinr <= cout;
  62. if((cdi.alu_op == ALU_MUL)|(cdi.alu_op == ALU_DIV)|(cdi.alu_op == ALU_SL)|(cdi.alu_op == ALU_SR))
  63. alu_rhi <= alu_rhit;
  64. end
  65. end
  66. alu#(.WORD(8)) alu0(
  67. .a(srcA),
  68. .b(srcB),
  69. .op(cdi.alu_op),
  70. .r(alu_rlo),
  71. .r_high(alu_rhit),
  72. .zero(alu_zero),
  73. .eq(alu_eq),
  74. .gt(alu_gt),
  75. .cin(cin), .cout(cout),
  76. .sign(alu_sign)
  77. // TODO: missing overflow
  78. );
  79. // ======================== //
  80. // Interrupt //
  81. // ======================== //
  82. word interrupt_flag, intre, intrr;
  83. always_ff@(posedge clk) begin
  84. if(rst) begin
  85. interrupt_flag <= 0;
  86. intre <= 0;
  87. intrr <= 0;
  88. end
  89. else begin
  90. if(interrupt) begin
  91. interrupt_flag <= com_rd;
  92. intrr <= pc;
  93. end
  94. if(cdi.intr_ctl == INTR_WE) intre <= imm[7:0];
  95. end
  96. end
  97. // ======================== //
  98. // Program Counter //
  99. // ======================== //
  100. logic pc_halted, intr_re, pcs, pchf; // Use immediate to branch
  101. word pc_off; // Program counter offset
  102. reg [15:0] pcn, pch, pca, pcb, pcn0; // Program Counter Previous, to add
  103. assign pchf = (cdi.pcop == PC_MEM) & ~pc_halted;
  104. always_comb begin
  105. pc_off = {
  106. 5'b0000_0,
  107. cdi.isize[0]&cdi.isize[1],
  108. cdi.isize[0]^cdi.isize[1],
  109. (~cdi.isize[1]&~cdi.isize[0])|(cdi.isize[1]&~cdi.isize[0])
  110. }; // Adding 1 to 2bit value.
  111. intr_re = cdi.intr_ctl == INTR_RE;
  112. casez({intr_re, interrupt, rst})
  113. 3'b000: pcb = pch;
  114. 3'b100: pcb = intrr;
  115. 3'b?10: pcb = intre;
  116. 3'b??1: pcb = 16'h0000;
  117. endcase
  118. case(cdi.pcop)
  119. PC_NONE: pcn0 = pcb;
  120. PC_MEM : pcn0 = mem_rd;
  121. PC_IMM : pcn0 = {imm[7:0], imm[15:8]};
  122. PC_IMM2: pcn0 = {imm[15:8], imm[23:16]};
  123. default: pcn0 = pcb;
  124. endcase
  125. pcn = (cdi.pcop == PC_IMM | cdi.pcop == PC_IMM2) ? pcn0 : pcn0 + pc_off;
  126. pca = (pchf) ? pch : pcn;
  127. pcs = intr_re | interrupt | rst;
  128. pc = (pcs) ? pcb : pca;
  129. end
  130. always_ff@(posedge clk) begin
  131. if(rst) begin
  132. pch <= 0;
  133. pc_halted <= 0;
  134. end else begin
  135. pch <= pcn;
  136. pc_halted <= pchf;
  137. end
  138. end
  139. // ======================== //
  140. // Stack //
  141. // ======================== //
  142. logic [15:0] sp, sp_add, sp_next, st_wr; // Stack pointer
  143. word st_reg, st_rd; // Stack data low byte reg
  144. logic [23:0] sp_addr;
  145. always_comb begin
  146. sp_add = (cdi.stackop == ST_ADD) ? 'h0001 : 'hffff;
  147. sp_next = sp + sp_add;
  148. sp_addr = {8'b1111_1111, (cdi.stackop == ST_ADD) ? sp_next[15:0] : sp[15:0]};
  149. st_rd = {mem_rd[7:0]};
  150. st_wr = (cdi.pcop == PC_IMM) ? pch : {8'h00, r1};
  151. //if(sp[0]) begin
  152. //st_wr = {'h00, r1};
  153. //st_rd = {mem_rd[7:0]};
  154. //end else begin
  155. //st_wr = {st_reg, r1};
  156. //st_rd = {mem_rd[15:8]};
  157. //end
  158. end
  159. always_ff@(posedge clk) begin
  160. if(rst) sp <= 'h0fff; // Highest memory address
  161. else begin
  162. if(cdi.stackop != ST_SKIP & ~pc_halted) sp <= sp_next;
  163. if(sp[0]) st_reg <= r1;
  164. end
  165. end
  166. // ======================== //
  167. // Memory //
  168. // ======================== //
  169. word mem_wr_hi; // High byte of memory store
  170. always_ff@(posedge clk) begin
  171. if(rst) mem_wr_hi <= '0;
  172. else if(cdi.selo == SO_MEMH) mem_wr_hi <= r1;
  173. end
  174. assign mem_wr = (cdi.stackop == ST_SUB) ? st_wr : {mem_wr_hi, r1};
  175. assign mem_addr = (cdi.stackop != ST_SKIP) ? sp_addr : {imm[7:0], imm[15:8], imm[23:16]};
  176. // COM Write
  177. assign com_wr = (cdi.selo == SO_COM) ? r1 : '0;
  178. assign com_addr = (cdi.selo == SO_COM) ? imm[7:0] : '0;
  179. //assign com_addr = 8'h06;
  180. //assign com_wr = pc[7:0];
  181. assign srcA = r1;
  182. always_comb begin
  183. case(cdi.selb)
  184. SB_REG : srcB = r2;
  185. SB_0 : srcB = 8'h00;
  186. SB_1 : srcB = 8'h01;
  187. SB_IMM : srcB = imm[7:0];
  188. default: srcB = r2;
  189. endcase
  190. end
  191. // ======================== //
  192. // Register File //
  193. // ======================== //
  194. word reg_wr, reg_wr1, reg_wr2;
  195. reg [1:0]reg_wra;
  196. reg reg_wr_en1;
  197. reg [1:0]reg_wr_mem;
  198. always_comb begin
  199. case(cdi.selr)
  200. SR_REG : reg_wr = r2;
  201. //SR_MEML: reg_wr = (cdi.stackop == ST_ADD) ? st_rd : mem_rd[7:0];
  202. //SR_MEMH: reg_wr = mem_rd[15:8];
  203. SR_ALUL: reg_wr = alu_rlo;
  204. SR_ALUH: reg_wr = alu_rhi;
  205. SR_IMM : reg_wr = imm[7:0];
  206. SR_COM : reg_wr = com_rd;
  207. SR_INTR: reg_wr = interrupt_flag;
  208. default: reg_wr = alu_rlo;
  209. endcase
  210. end
  211. always_ff@(posedge clk) begin
  212. if(rst) begin
  213. reg_wr1 <= 0;
  214. reg_wr_en1 <= 0;
  215. reg_wr_mem <= 0;
  216. end else begin
  217. reg_wr1 <= reg_wr;
  218. reg_wr_en1 <= cdi.rw_en;
  219. reg_wra <= cdi.a3;
  220. reg_wr_mem <= {cdi.selr == SR_MEML, cdi.selr == SR_MEMH};
  221. end
  222. end
  223. always_comb begin
  224. case(reg_wr_mem)
  225. 2'b10: reg_wr2 = mem_rd[7:0];
  226. 2'b01: reg_wr2 = mem_rd[15:8];
  227. default: reg_wr2 = reg_wr1;
  228. endcase
  229. end
  230. reg_file reg0(.clk(clk), .rst(rst),
  231. .rd_addr1(cdi.a1),
  232. .rd_addr2(cdi.a2),
  233. .rd_data1(r1),
  234. .rd_data2(r2),
  235. .wr_addr(reg_wra),
  236. .wr_data(reg_wr2),
  237. .wr_en(reg_wr_en1)
  238. );
  239. endmodule