📄 dspuva16.v
字号:
`define OP_RET (`OP_NOP & (IR[11:9] == 3'h1)) // RET (or IRET)
`define OP_COND_ASG (`OP_ARITH & ~IR[13]) // IF (flag) rD = rT|K
//--------------------------//
// Instruction Register: IR //
//--------------------------//
reg OldMAC; // Registers 'one' if last instruction was a MAC one
reg [3:0] OldRegD; // Destination Registry of a MAC instruction
reg [3:0] FlagSelect; // Flag Selected by the current instruction
always @(posedge CLK or posedge ResetFF)
begin
if (ResetFF) OldMAC <= 1'b0;
else if (`PHASE1) OldMAC <= `OP_MAC;
if (ResetFF) OldRegD <= r0;
else if (`PHASE1) OldRegD <= rD;
if (ResetFF) FlagSelect <= 4'b0000;
else if (`PHASE1) FlagSelect <= CODEdata[11:8];
if (ResetFF) IR <= 16'h0000;
else if (`PHASE1) IR <= CODEdata;
else if ((`PHASE2 | `PHASE3) & `OP_COND_ASG) IR <= {OpCode, rS, rS, rT};
end
//---------------------//
// Program Counter: PC //
//---------------------//
reg PCinc, PCflag; // Auxiliary
wire [12:0] PCmask = (PCflag) ? {RelAddr[7],RelAddr[7],RelAddr[7],RelAddr[7], RelAddr[7:0], 1'b1} : 13'h0001;
wire [12:0] PCadder = {PC, PCinc} + PCmask;
always @(posedge CLK or posedge ResetFF)
begin
if (ResetFF)
begin
PC <= 12'h000;
PCinc <= 1'b0;
PCflag <= 1'b0;
end
else
begin
if (`PHASE3 & `OP_GOTO) PC <= (AbsAddr << MODEL); // GOTO
else if (`PHASE3 & `OP_RET) PC <= ACC[11:0]; // RET
else PC <= PCadder[12:1]; // Others
PCinc <= (`PHASE0) | (`PHASE2 & (rT == r0) & `OP_ALUMAC); // OpFetch or K used
PCflag <= `PHASE2 & `OP_JP & Flag; // '1' if relative jump
end
end
assign CODEaddr = PC[MODEL+7:0]; // The logic not used is optimized away
//----------------------------------------------//
// Bank of 16 Internal 24-bit Registers: r0-r15 //
//----------------------------------------------//
reg [23:0] RegsBank[0:15]; // Register Bank Memory
reg [3:0] RegAddr; // Register Bank Address
wire RegWE = (`PHASE0 & `OP_ALU) // ALU operation
| (`PHASE0 & `OP_IN) // INport command
| (`PHASE1 & OldMAC) // MAC operation
| (`PHASE3 & `OP_CALL); // CALL command
always @(posedge CLK or posedge ResetFF)
begin
if (ResetFF) RegAddr <= r0;
else case (State) // synopsys parallel_case full_case
st0: RegAddr <= OldRegD; // Destination for MAC
st1: RegAddr <= CODEdata[3:0]; // Second Operand
st2: RegAddr <= rS; // First Operand
st3: RegAddr <= rD; // Destination for ALU
endcase
end
always @(posedge CLK)
begin
if (RegWE) RegsBank[RegAddr] <= DataBus; // Sync Write from DataBus
end
assign RegOut = RegsBank[RegAddr]; // Async Read
always @(posedge CLK or posedge ResetFF) // Sync Register Output
begin
if (ResetFF) ACC <= 24'h000000;
else ACC <= RegOut;
end
//--------------------------------------------------//
// Multiplier-Accumulator and Arithmetic-Logic Unit //
//--------------------------------------------------//
wire [23:0] ALUmac, ALUlogic, ALUarith; // ALU outputs
wire [23:0] RegS = (rS == r0) ? 24'h000000 : RegOut; // rS or 0
wire [23:0] RegT = (rT == r0) ? {CODEdata, 8'h00} : ACC; // rT or K
ALUuva16 ALUandMAC
(
.Clk (CLK),
.InA (RegS),
.InB (RegT),
.InC (RegOut),
.Phase (State),
.OpCode (OpCode),
.FlagIn (Flag),
.Vflag (ALUoverflow),
.OutMAC (ALUmac),
.OutLogic (ALUlogic),
.OutArith (ALUarith)
);
//-------------------//
// Internal Data Bus //
//-------------------//
assign DataBus = (`PHASE0 & `OP_ARITH) ? ALUarith : 24'bz; // Arithmetic operation
assign DataBus = (`PHASE0 & `OP_LOGIC) ? ALUlogic : 24'bz; // Logic operation
assign DataBus = (`PHASE1) ? ALUmac : 24'bz; // MAC operation
assign DataBus = (`PHASE3 | `PHASE2) ? {12'h000,PC} : 24'bz; // Return Address on CALLs
assign DataBus = (`PHASE0 & `OP_CTRL) ? {PORTin, 8'h00} : 24'bz; // External input through PORT
assign DataBus = (`PHASE0 & `OP_MAC) ? 24'hFFFFFF : 24'bz; // Otherwise, pull-up
//-------//
// Flags //
//-------//
`define EQ 3'b000
`define NE 3'b001
`define OV 3'b010
`define NV 3'b011
`define GE 3'b100
`define GT 3'b101
`define LE 3'b110
`define LT 3'b111
reg ZFF, SFF, VFF; // Internal flags: zero, sign and overflow.
always @(posedge CLK or posedge ResetFF)
begin
if (ResetFF)
{ZFF, SFF, VFF} <= 3'b000;
else if (`PHASE0) // Updates flags on ALU and INPORT ops
begin
ZFF <= (DataBus == 24'h000000); // One if null result
SFF <= DataBus[23]; // One if negative result
VFF <= ALUoverflow; // One if overflow on add/sub
end
end
always @(ZFF or SFF or VFF or FlagSelect)
begin
case (FlagSelect[2:0]) // synopsys parallel_case full_case
`EQ: Flag = ZFF; // equal (to zero)
`NE: Flag = ~ZFF; // not equal (to zero)
`OV: Flag = VFF; // overflow
`NV: Flag = ~VFF; // not overflow
`GE: Flag = ~SFF | ZFF; // greater or equal (to zero)
`GT: Flag = ~SFF & ~ZFF; // greater than (zero)
`LE: Flag = SFF | ZFF; // less or equal (to zero)
`LT: Flag = SFF & ~ZFF; // less than (zero)
endcase
end
//-----------------------------------//
// External Interface: 128 I/O ports //
//-----------------------------------//
reg [6:0] PORTaddr; // Port Address Register
reg IOread, IOwrite;
always @(posedge CLK or posedge ResetFF)
begin
if (ResetFF)
PORTaddr <= 7'h00;
else if (`PHASE2)
begin
`ifdef LOW_POWER
if (`OP_IO) // Only changes when used
`endif
PORTaddr <= (`OUT_IN) ? {IR[6:4],IR[11:8]} : IR[6:0]; // OUT or IN operation
end
if (ResetFF) IOwrite <= 1'b0;
else IOwrite <= `PHASE2 & `OP_OUT; // On the last subcycle
if (ResetFF) IOread <= 1'b0;
else IOread <= `PHASE3 & `OP_IN; // On the first subcycle
end
assign PORTout = ACC[23:8];
// External I/O ports must decode PORTaddr
// to gain control on PORTin bus (else pull-up)
endmodule // DSPuva16
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -