📄 soc-gr0040.v
字号:
// Copyright (C) 2000, Gray Research LLC.// All rights reserved. Use subject to the// XSOC License Agreement, see LICENSE file,// http://www.fpgapcu.org/xsoc/LICENSE.html.// Version 2001.03.09 `define W 16 // register width`define N 15 // register MSB`define AN 15 // address MSB`define IN 15 // instruction MSB module gr0040( clk, rst, i_ad_rst, insn_ce, i_ad, insn, hit, int_en, d_ad, rdy, sw, sb, do, lw, lb, data); input clk; // clock input rst; // reset (sync) input [`AN:0] i_ad_rst; // reset vector output insn_ce; // insn clock enable output [`AN:0] i_ad;// next insn address input [`IN:0] insn;// current insn input hit; // insn is valid output int_en; // OK to intr. now output [`AN:0] d_ad;// load/store addr input rdy; // memory ready output sw, sb; // executing sw (sb) output [`N:0] do; // data to store output lw, lb; // executing lw (lb) inout [`N:0] data; // results, load data // opcode decoding `define JAL (op==0) `define ADDI (op==1) `define RR (op==2) `define RI (op==3) `define LW (op==4) `define LB (op==5) `define SW (op==6) `define SB (op==7) `define IMM (op==8) `define Bx (op==9) `define ALU (`RR|`RI) // fn decoding `define ADD (fn==0) `define SUB (fn==1) `define AND (fn==2) `define XOR (fn==3) `define ADC (fn==4) `define SBC (fn==5) `define CMP (fn==6) `define SRL (fn==7) `define SRA (fn==8) `define SUM (`ADD|`SUB|`ADC|`SBC) `define LOG (`AND|`XOR) `define SR (`SRL|`SRA) // instruction decoding wire [3:0] op = insn[15:12]; wire [3:0] rd = insn[11:8]; wire [3:0] rs = insn[7:4]; wire [3:0] fn = `RI ? insn[7:4] : insn[3:0]; wire [3:0] imm = insn[3:0]; wire [11:0] i12 = insn[11:0]; wire [3:0] cond = insn[11:8]; wire [7:0] disp = insn[7:0]; // register file and program counter wire valid_insn_ce = hit & insn_ce; wire rf_we = valid_insn_ce & ~rst & ((`ALU&~`CMP)|`ADDI|`LB|`LW|`JAL); wire [`N:0] dreg, sreg; // d, s registers ram16x16d regfile(.clk(clk), .we(rf_we), .wr_ad(rd), .ad(`RI ? rd : rs), .d(data), .wr_o(dreg), .o(sreg)); reg [`AN:0] pc; // program counter // immediate prefix reg imm_pre; // immediate prefix reg [11:0] i12_pre; // imm prefix value always @(posedge clk) if (rst) imm_pre <= 0; else if (valid_insn_ce) imm_pre <= `IMM; always @(posedge clk) if (valid_insn_ce) i12_pre <= i12; // immediate operand wire word_off = `LW|`SW|`JAL; wire sxi = (`ADDI|`ALU) & imm[3]; wire [10:0] sxi11 = {11{sxi}}; wire i_4 = sxi | (word_off&imm[0]); wire i_0 = ~word_off&imm[0]; wire [`N:0] imm16 = imm_pre ? {i12_pre,imm} : {sxi11,i_4,imm[3:1],i_0}; // operand selection wire [`N:0] a = `RR ? dreg : imm16; wire [`N:0] b = sreg; // adder/subtractor wire [`N:0] sum; wire add = ~(`ALU&(`SUB|`SBC|`CMP)); reg c; // carry-in if adc/sbc wire ci = add ? c : ~c; wire c_W, x; addsub adder(.add(add), .ci(ci), .a(a), .b(b), .sum(sum), .x(x), .co(c_W)); // condition codes wire z = sum == 0; // zero wire n = sum[`N]; // negative wire co = add ? c_W : ~c_W; // carry-out wire v = c_W^sum[`N]^a[`N]^b[`N];// overflow reg ccz, ccn, ccc, ccv; // CC vector always @(posedge clk) if (rst) {ccz,ccn,ccc,ccv} <= 0; else if (valid_insn_ce) {ccz,ccn,ccc,ccv} <= {z,n,co,v}; // add/subtract-with-carry state always @(posedge clk) if (rst) c <= 0; else if (valid_insn_ce) c <= co & (`ALU&(`ADC|`SBC)); // logic unit wire [`N:0] log = fn[0] ? a^b : a&b; // shift right wire [`N:0] sr = {(`SRA?b[`N]:0),b[`N:1]}; // result mux wire sum_en = (`ALU&`SUM) | `ADDI; assign data = sum_en ? sum : 16'bz; assign data = (`ALU&`LOG) ? log : 16'bz; assign data = (`ALU&`SR) ? sr : 16'bz; assign data = `JAL ? pc : 16'bz; // conditional branch decoding `define BR 0 `define BEQ 2 `define BC 4 `define BV 6 `define BLT 8 `define BLE 'hA `define BLTU 'hC `define BLEU 'hE // conditional branches reg br, t; always @(hit or cond or op or ccz or ccn or ccc or ccv) begin case (cond&4'b1110) `BR: t = 1; `BEQ: t = ccz; `BC: t = ccc; `BV: t = ccv; `BLT: t = ccn^ccv; `BLE: t = (ccn^ccv)|ccz; `BLTU: t = ~ccz&~ccc; `BLEU: t = ccz|~ccc; endcase br = hit & `Bx & (cond[0] ? ~t : t); end // jumps, branches, insn fetch wire [6:0] sxd7 = {7{disp[7]}}; wire [`N:0] sxd16 = {sxd7,disp,1'b0}; wire [`N:0] pcinc = br ? sxd16 : {hit,1'b0}; wire [`N:0] pcincd = pc + pcinc; assign i_ad = (hit & `JAL) ? sum : pcincd; always @(posedge clk) if (rst) pc <= i_ad_rst; else if (valid_insn_ce) pc <= i_ad; wire mem = hit & (`LB|`LW|`SB|`SW); assign insn_ce = rst | ~(mem & ~rdy); // data loads, stores assign d_ad = sum; assign do = dreg; assign lw = hit & `LW; assign lb = hit & `LB; assign sw = hit & `SW; assign sb = hit & `SB; // interrupt support assign int_en = hit & ~(`IMM|`ALU&(`ADC|`SBC|`CMP)); endmodule module addsub(add, ci, a, b, sum, x, co); input add, ci; input [15:0] a, b; output [15:0] sum; output x, co; assign {co,sum,x}= add ? {a,ci}+{b,1'b1} : {a,ci}-{b,1'b1}; endmodule module gr0041( clk, rst, i_ad_rst, int_req, insn_ce, i_ad, insn, hit, zero_insn, d_ad, rdy, sw, sb, do, lw, lb, data); input clk; // clock input rst; // reset (sync) input [`AN:0] i_ad_rst; // reset vector input int_req; // interrupt request output insn_ce; // insn clock enable output [`AN:0] i_ad;// next insn address input [`IN:0] insn;// current insn input hit; // insn is valid output zero_insn; // force insn to 0000 output [`AN:0] d_ad;// load/store addr input rdy; // memory ready output sw, sb; // executing sw (sb) output [`N:0] do; // data to store output lw, lb; // executing lw (lb) inout [`N:0] data; // results, load data wire int_en; // interrupt enabled reg int; // call intr in progress // interrupt request rising edge detection reg int_req_last, int_pend; always @(posedge clk) if (rst) int_req_last <= 0; else int_req_last <= int_req; always @(posedge clk) if (rst) int_pend <= 0; else if (int) int_pend <= 0; else if (int_req && ~int_req_last) int_pend <= 1; // insert intr at an auspicious time wire int_nxt = int_pend & int_en & ~int; always @(posedge clk) if (rst) int <= 0; else if (insn_ce) int <= int_nxt; // on int, fetch 0000 and execute 0002, // which is 'jal r0,2(r0)' -- call intr assign zero_insn = int_nxt; wire [`N:0] insn_int = insn | {int, 1'b0}; gr0040 p( .clk(clk), .rst(rst), .i_ad_rst(i_ad_rst), .insn_ce(insn_ce), .i_ad(i_ad), .insn(insn_int), .hit(hit | int), .int_en(int_en), .d_ad(d_ad), .rdy(rdy), .sw(sw), .sb(sb), .do(do), .lw(lw), .lb(lb), .data(data)); endmodule // on-chip peripheral bus defines`define IO // on-chip periphs enabled`define CN 31 // ctrl bus MSB`define CRAN 7 // control reg addr MSB`define DN 15 // data bus MSB`define SELN 7 // select bus MSB module soc(clk, rst, par_i, par_o); input clk; // clock input rst; // reset (sync) input [7:0] par_i; // parallel inputs output [7:0] par_o; // parallel outputs // // processor ports and control signals // wire [`AN:0] i_ad, d_ad; wire [`N:0] insn, do; tri [`N:0] data; wire int_req, zero_insn; wire rdy, sw, sb, lw, lb; gr0041 p( .clk(clk), .rst(rst), .i_ad_rst(16'h0020), .int_req(int_req), .insn_ce(insn_ce), .i_ad(i_ad), .insn(insn), .hit(~rst), .zero_insn(zero_insn), .d_ad(d_ad), .rdy(rdy), .sw(sw), .sb(sb), .do(do), .lw(lw), .lb(lb), .data(data)); // // rdy (wait state) control // reg loaded; // load data in bram out regs always @(posedge clk) if (rst) loaded <= 0; else if (insn_ce) loaded <= 0; else loaded <= (lw|lb); `ifdef IO wire io_nxt = d_ad[`AN];`else wire io_nxt = 0;`endif reg io; // peripheral I/O access underway always @(posedge clk) if (rst) io <= 0; else if (insn_ce) io <= 0; else io <= io_nxt; wire io_rdy; assign rdy = ~io_nxt&~((lw|lb)&~loaded) | io&io_rdy | rst; // // embedded RAM // wire h_we = ~rst&~io_nxt&(sw|sb&~d_ad[0]); wire l_we = ~rst&~io_nxt&(sw|sb&d_ad[0]); wire [7:0] do_h = sw ? do[15:8] : do[7:0]; wire [`N:0] di; RAMB4_S8_S8 ramh(
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -