Revert to default
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
# Lattice Diamond 实现输出目录
|
||||
# 根目录 .gitignore 已覆盖大部分 pattern,此处仅确保 impl1/ 被忽略
|
||||
impl1/
|
||||
@@ -0,0 +1,9 @@
|
||||
[Runmanager]
|
||||
Geometry=@ByteArray(\x1\xd9\xd0\xcb\0\x1\0\0\0\0\0\0\0\0\x3\x30\0\0\x1!\0\0\x4\x11\0\0\0\0\0\0\0\0\xff\xff\xff\xff\xff\xff\xff\xff\0\0\0\0\0\0)
|
||||
windowState=@ByteArray(\0\0\0\xff\0\0\0\0\xfd\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x4\0\0\0\x4\0\0\0\b\0\0\0\b\xfc\0\0\0\x1\0\0\0\0\0\0\0\x1\xff\xff\xff\xff\x3\0\0\0\0\xff\xff\xff\xff\0\0\0\0\0\0\0\0)
|
||||
headerState=@ByteArray(\0\0\0\xff\0\0\0\0\0\0\0\x1\0\0\0\x1\0\0\0\0\x1\0\0\0\0\0\0\0\0\0\0\0\x16\0\xe0?\0\0\0\t\0\0\0\x10\0\0\0\x64\0\0\0\xf\0\0\0\x64\0\0\0\xe\0\0\0\x64\0\0\0\r\0\0\0\x64\0\0\0\x15\0\0\0\x64\0\0\0\x14\0\0\0\x64\0\0\0\x13\0\0\0\x64\0\0\0\x12\0\0\0\x64\0\0\0\x11\0\0\0\x64\0\0\x4\xd3\0\0\0\x16\x1\x1\0\x1\0\0\0\0\0\0\0\0\0\0\0\0\x64\xff\xff\xff\xff\0\0\0\x81\0\0\0\0\0\0\0\x3\0\0\0#\0\0\0\x1\0\0\0\x2\0\0\x4\xb0\0\0\0\f\0\0\0\0\0\0\0\0\0\0\0\t\0\0\0\0)
|
||||
|
||||
[impl1%3CStrategy1%3E]
|
||||
isChecked=false
|
||||
isHidden=false
|
||||
isExpanded=false
|
||||
@@ -0,0 +1,2 @@
|
||||
[General]
|
||||
Export.auto_tasks=Bitgen, Jedecgen
|
||||
@@ -0,0 +1,3 @@
|
||||
[General]
|
||||
COLUMN_POS_INFO_NAME_-1_0=Prioritize
|
||||
COLUMN_POS_INFO_NAME_-1_1=PIO Register
|
||||
@@ -0,0 +1,76 @@
|
||||
[General]
|
||||
pin_sort_type=0
|
||||
pin_sort_ascending=true
|
||||
sig_sort_type=0
|
||||
sig_sort_ascending=true
|
||||
active_Sheet=Pin Assignments
|
||||
|
||||
[Port%20Assignments]
|
||||
Name="193,0"
|
||||
Group%20By="88,1"
|
||||
Pin="79,2"
|
||||
BANK="60,3"
|
||||
BANK_VCC="88,4"
|
||||
VREF="60,5"
|
||||
IO_TYPE="147,6"
|
||||
PULLMODE="97,7"
|
||||
DRIVE="67,8"
|
||||
SLEWRATE="91,9"
|
||||
CLAMP="67,10"
|
||||
OPENDRAIN="95,11"
|
||||
DIFFRESISTOR="116,12"
|
||||
DIFFDRIVE="95,13"
|
||||
HYSTERESIS="102,14"
|
||||
Outload%20%28pF%29="116,15"
|
||||
MaxSkew="81,16"
|
||||
Clock%20Load%20Only="137,17"
|
||||
SwitchingID="109,18"
|
||||
Ground%20plane%20PCB%20noise%20%28mV%29="221,19"
|
||||
Power%20plane%20PCB%20noise%20%28mV%29="214,20"
|
||||
SSO%20Allowance%28%25%29="144,21"
|
||||
sort_columns="Name,Ascending"
|
||||
|
||||
[Pin%20Assignments]
|
||||
Pin="93,0"
|
||||
Pad%20Name="88,1"
|
||||
Dual%20Function="158,2"
|
||||
Polarity="88,3"
|
||||
BANK="0,4"
|
||||
BANK_VCC="88,5"
|
||||
IO_TYPE="147,6"
|
||||
Signal%20Name="177,7"
|
||||
Signal%20Type="115,8"
|
||||
sort_columns="Pin,Ascending"
|
||||
|
||||
[Clock%20Resource]
|
||||
Clock%20Type="100,ELLIPSIS"
|
||||
Clock%20Name="100,ELLIPSIS"
|
||||
Selection="100,ELLIPSIS"
|
||||
|
||||
[Global%20Preferences]
|
||||
Preference%20Name="231,ELLIPSIS"
|
||||
Preference%20Value="236,ELLIPSIS"
|
||||
|
||||
[Cell%20Mapping]
|
||||
Type="100,ELLIPSIS"
|
||||
Name="223,ELLIPSIS"
|
||||
Din\Dout="83,ELLIPSIS"
|
||||
PIO%20Register="100,ELLIPSIS"
|
||||
|
||||
[Route%20Priority]
|
||||
Type="100,ELLIPSIS"
|
||||
Name="100,ELLIPSIS"
|
||||
Prioritize="100,ELLIPSIS"
|
||||
|
||||
[Timing%20Preferences]
|
||||
Preference%20Name="129,ELLIPSIS"
|
||||
Preference%20Value="111,ELLIPSIS"
|
||||
Preference%20Unit="103,ELLIPSIS"
|
||||
|
||||
[Group]
|
||||
Group%20Type\Name="134,ELLIPSIS"
|
||||
Value="42,ELLIPSIS"
|
||||
|
||||
[Misc%20Preferences]
|
||||
Preference%20Name="117,ELLIPSIS"
|
||||
Preference%20Value="111,ELLIPSIS"
|
||||
@@ -0,0 +1,215 @@
|
||||
module BUS_Con (
|
||||
input i_sys_clk,
|
||||
input i_rst_n,
|
||||
|
||||
// SPI Interface
|
||||
input i_sclk,
|
||||
input i_mosi,
|
||||
input i_cs,
|
||||
output o_miso, // <-- MISO Logic added here
|
||||
|
||||
// Local Interface
|
||||
output o_rvalid, // (Typo in original: o_rvalid)
|
||||
input i_rvalid, // Valid signal from Backend (Data is ready)
|
||||
input i_wvalid,
|
||||
output o_wready,
|
||||
input i_reg_busy,
|
||||
input [23:0] i_rdata, // Data from Backend to send to Master
|
||||
output o_wr,
|
||||
output o_cmd_valid,
|
||||
output [23:0] o_data,
|
||||
output [6:0] o_addr,
|
||||
output o_err
|
||||
);
|
||||
|
||||
// --- 1. Synchronization ---
|
||||
reg [1:0] cs_sync;
|
||||
reg [1:0] sclk_sync;
|
||||
reg [1:0] mosi_sync;
|
||||
|
||||
wire cs_active;
|
||||
wire cs_rise;
|
||||
wire sclk_rise; // For Sampling MOSI
|
||||
wire sclk_fall; // For Shifting MISO
|
||||
wire mosi_data;
|
||||
|
||||
|
||||
always @(posedge i_sys_clk) begin
|
||||
if (!i_rst_n) begin
|
||||
cs_sync <= 2'b11;
|
||||
sclk_sync <= 2'b00;
|
||||
mosi_sync <= 2'b00;
|
||||
end else begin
|
||||
cs_sync <= {cs_sync[0], i_cs};
|
||||
sclk_sync <= {sclk_sync[0], i_sclk};
|
||||
mosi_sync <= {mosi_sync[0], i_mosi};
|
||||
end
|
||||
end
|
||||
|
||||
assign cs_active = ~cs_sync[1];
|
||||
assign cs_rise = (!cs_sync[1] && cs_sync[0]);
|
||||
|
||||
// SPI Mode 0: Sample MOSI on Rising, Shift MISO on Falling
|
||||
assign sclk_rise = (!sclk_sync[1] && sclk_sync[0]);
|
||||
assign sclk_fall = (sclk_sync[1] && !sclk_sync[0]); // Logic for MISO
|
||||
assign mosi_data = mosi_sync[1];
|
||||
|
||||
// --- 2. MOSI (Receive) Logic ---
|
||||
reg [31:0] recv_reg;
|
||||
reg [5:0] bit_cnt;
|
||||
reg data_ready;
|
||||
reg err_flag;
|
||||
reg [1:0] state;
|
||||
//
|
||||
reg [31:0] tx_buffer; // Holds data waiting for the next CS Low
|
||||
reg [31:0] miso_shift; // The actual shifter
|
||||
// Output Registers
|
||||
reg [6:0] addr_out;
|
||||
reg [23:0] data_out;
|
||||
reg wr_out;
|
||||
reg cmd_valid_out;
|
||||
|
||||
//
|
||||
localparam IDLE = 2'b00;
|
||||
localparam CMD_SENT = 2'b01;
|
||||
localparam WAIT_BUSY = 2'b10;
|
||||
localparam DONE = 2'b11;
|
||||
|
||||
|
||||
always @(posedge i_sys_clk) begin
|
||||
if (!i_rst_n) begin
|
||||
recv_reg <= 32'd0;
|
||||
bit_cnt <= 6'd0;
|
||||
data_ready <= 1'b0;
|
||||
err_flag <= 1'b0;
|
||||
end
|
||||
else begin
|
||||
data_ready <= 1'b0;
|
||||
|
||||
if (cs_active) begin
|
||||
if (sclk_rise) begin
|
||||
recv_reg <= {recv_reg[30:0], mosi_data};
|
||||
bit_cnt <= bit_cnt + 1'b1;
|
||||
end
|
||||
else if (cs_rise) begin
|
||||
if (bit_cnt == 6'd32) begin
|
||||
data_ready <= 1'b1;
|
||||
err_flag <= 1'b0;
|
||||
bit_cnt <= 6'd0;
|
||||
end
|
||||
else if (bit_cnt != 0) begin
|
||||
err_flag <= 1'b1;
|
||||
bit_cnt <= 6'd0;
|
||||
recv_reg <= 'd0;
|
||||
end
|
||||
end
|
||||
end
|
||||
if (state == DONE) begin
|
||||
recv_reg <= 'd0;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// --- 3. MISO (Transmit) Logic ---
|
||||
// Protocol: We shift out 32 bits.
|
||||
// Format: [8 bit Status/Padding] + [24 bit i_rdata]
|
||||
|
||||
|
||||
// Capture data from backend when valid
|
||||
always @(posedge i_sys_clk) begin
|
||||
if (!i_rst_n) begin
|
||||
tx_buffer <= 32'd0;
|
||||
end else begin
|
||||
// If backend provides valid read data, store it.
|
||||
// We pad the top 8 bits with Zeros (or you can put status flags here)
|
||||
if (i_rvalid) begin
|
||||
tx_buffer <= {8'h00, i_rdata};
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// Shift data out
|
||||
always @(posedge i_sys_clk) begin
|
||||
if (!i_rst_n) begin
|
||||
miso_shift <= 32'd0;
|
||||
end else begin
|
||||
if (!cs_active) begin
|
||||
// Pre-load the shifter while CS is High
|
||||
// This ensures Bit 31 is ready BEFORE the first clock edge
|
||||
miso_shift <= tx_buffer;
|
||||
end else begin
|
||||
// Shift on Falling Edge (Master samples on Rising)
|
||||
if (sclk_fall) begin
|
||||
miso_shift <= {miso_shift[30:0], 1'b0};
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// Tri-state MISO when CS is high (optional, usually good practice)
|
||||
// If your board doesn't need tristate, just use: assign o_miso = miso_shift[31];
|
||||
assign o_miso = (cs_active) ? miso_shift[31] : 1'bz;
|
||||
|
||||
// --- 4. Register Control FSM ---
|
||||
|
||||
|
||||
|
||||
always @(posedge i_sys_clk) begin
|
||||
if (!i_rst_n) begin
|
||||
state <= IDLE;
|
||||
cmd_valid_out <= 1'b0;
|
||||
addr_out <= 7'd0;
|
||||
data_out <= 24'd0;
|
||||
wr_out <= 1'b0;
|
||||
end else begin
|
||||
case (state)
|
||||
IDLE: begin
|
||||
if (data_ready) begin
|
||||
addr_out <= recv_reg[30:24];
|
||||
data_out <= recv_reg[23:0];
|
||||
wr_out <= recv_reg[31];
|
||||
|
||||
if (!i_reg_busy) begin
|
||||
cmd_valid_out <= 1'b1;
|
||||
state <= CMD_SENT;
|
||||
end else begin
|
||||
state <= WAIT_BUSY;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
WAIT_BUSY: begin
|
||||
if (!i_reg_busy) begin
|
||||
cmd_valid_out <= 1'b1;
|
||||
state <= CMD_SENT;
|
||||
end
|
||||
end
|
||||
|
||||
CMD_SENT: begin
|
||||
cmd_valid_out <= 1'b0;
|
||||
state <= DONE;
|
||||
end
|
||||
|
||||
DONE: begin
|
||||
if (!i_reg_busy) begin
|
||||
state <= IDLE;
|
||||
addr_out <= 'd0;
|
||||
data_out <= 'd0;
|
||||
wr_out <= 'd0;
|
||||
end
|
||||
end
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
assign o_addr = addr_out;
|
||||
assign o_data = data_out;
|
||||
assign o_wr = wr_out;
|
||||
assign o_cmd_valid = cmd_valid_out;
|
||||
assign o_err = err_flag;
|
||||
assign o_wready = (state == IDLE);
|
||||
|
||||
// Pass through unused signal or hook it up if needed
|
||||
assign o_rvalid = 1'b0;
|
||||
|
||||
endmodule
|
||||
@@ -0,0 +1,91 @@
|
||||
module CPLD_Con (
|
||||
input i_sys_clk,
|
||||
input i_rst_n,
|
||||
input i_con_exec,
|
||||
input [23:0]i_freq_relay1,
|
||||
input [23:0]i_freq_relay2,
|
||||
input [23:0]i_freq_relay3,
|
||||
input [23:0]i_freq_relay4,
|
||||
output o_con_done,
|
||||
output [3:0]o_PMU_RC,
|
||||
output o_err
|
||||
);
|
||||
|
||||
//Relay Reg
|
||||
reg [3:0] PMU_RC;
|
||||
|
||||
//Flags
|
||||
reg exec_flag;
|
||||
reg err_flag;
|
||||
reg [3:0]slot_exec_flag;
|
||||
reg done_flag;
|
||||
|
||||
//Counter
|
||||
reg [15:0]delay_cnt;
|
||||
|
||||
always @(posedge i_sys_clk) begin
|
||||
if (i_rst_n == 1'b0) begin
|
||||
delay_cnt <= 'd0;
|
||||
end
|
||||
else begin
|
||||
if (exec_flag == 1'b1) begin
|
||||
delay_cnt <= delay_cnt + 1'd1;
|
||||
end
|
||||
else begin
|
||||
delay_cnt <= 'd0;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge i_sys_clk) begin
|
||||
if (i_rst_n == 1'b0) begin
|
||||
exec_flag <= 1'b0;
|
||||
err_flag <= 1'b0;
|
||||
slot_exec_flag <= 'd0;
|
||||
done_flag <= 'd1;
|
||||
PMU_RC <= 4'b1111;
|
||||
end
|
||||
else begin
|
||||
if ((i_con_exec == 1'b1) & (exec_flag == 1'b0)) begin
|
||||
exec_flag <= 1'b1;
|
||||
done_flag <= 1'b0;
|
||||
//To DO: More Sanity Check?
|
||||
if ( (i_freq_relay1[0] + i_freq_relay2[0] + i_freq_relay3[0] + i_freq_relay4[0]) > 2'd1 ) begin
|
||||
err_flag <= 1'b1;
|
||||
end
|
||||
else begin
|
||||
slot_exec_flag[0] <= i_freq_relay1[0];
|
||||
slot_exec_flag[1] <= i_freq_relay2[0];
|
||||
slot_exec_flag[2] <= i_freq_relay3[0];
|
||||
slot_exec_flag[3] <= i_freq_relay4[0];
|
||||
end
|
||||
end
|
||||
else if (exec_flag == 1'b1) begin
|
||||
case (slot_exec_flag)
|
||||
4'b0001: begin
|
||||
PMU_RC <= 4'b1111;
|
||||
end
|
||||
4'b0010: begin
|
||||
PMU_RC <= 4'b1100;
|
||||
end
|
||||
4'b0100: begin
|
||||
PMU_RC <= 4'b1010;
|
||||
end
|
||||
4'b1000: begin
|
||||
PMU_RC <= 4'b0110;
|
||||
end
|
||||
endcase
|
||||
done_flag <= 1'b1;
|
||||
end
|
||||
end
|
||||
if (done_flag == 1) begin
|
||||
exec_flag <= 1'b0;
|
||||
end
|
||||
end
|
||||
|
||||
assign o_con_done = done_flag;
|
||||
assign o_PMU_RC = PMU_RC;
|
||||
assign o_err = err_flag;
|
||||
|
||||
|
||||
endmodule
|
||||
@@ -0,0 +1 @@
|
||||
VERSION=20110520
|
||||
@@ -0,0 +1,38 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<BaliProject version="3.2" title="NewExtIns_CPLD3" device="LCMXO2-7000HC-4FG484C" default_implementation="impl1">
|
||||
<Options/>
|
||||
<Implementation title="impl1" dir="impl1" description="impl1" synthesis="synplify" default_strategy="Strategy1">
|
||||
<Options def_top="RelayConTop" top="RelayConTop"/>
|
||||
<Source name="RelayConTop.v" type="Verilog" type_short="Verilog">
|
||||
<Options top_module="RelayConTop"/>
|
||||
</Source>
|
||||
<Source name="BUS_Con.v" type="Verilog" type_short="Verilog">
|
||||
<Options/>
|
||||
</Source>
|
||||
<Source name="Reg_file.v" type="Verilog" type_short="Verilog">
|
||||
<Options/>
|
||||
</Source>
|
||||
<Source name="tb_RelayConTop.sv" type="Verilog" type_short="Verilog" syn_sim="SimOnly">
|
||||
<Options VerilogStandard="System Verilog"/>
|
||||
</Source>
|
||||
<Source name="CPLD_Con.v" type="Verilog" type_short="Verilog">
|
||||
<Options/>
|
||||
</Source>
|
||||
<Source name="CPLD3_Debug.rva" type="Reveal Analyzer Project File" type_short="RVA">
|
||||
<Options/>
|
||||
</Source>
|
||||
<Source name="NewExtIns_CPLD3.lpf" type="Logic Preference" type_short="LPF">
|
||||
<Options/>
|
||||
</Source>
|
||||
<Source name="debug.rvl" type="Reveal" type_short="Reveal">
|
||||
<Options/>
|
||||
</Source>
|
||||
<Source name="impl1/impl1.xcf" type="Programming Project File" type_short="Programming">
|
||||
<Options/>
|
||||
</Source>
|
||||
<Source name="tb_RelayConTop/tb_RelayConTop.spf" type="Simulation Project File" type_short="SPF">
|
||||
<Options/>
|
||||
</Source>
|
||||
</Implementation>
|
||||
<Strategy name="Strategy1" file="NewExtInsRelay1.sty"/>
|
||||
</BaliProject>
|
||||
@@ -0,0 +1,29 @@
|
||||
rvl_alias "i_sys_clk" "i_sys_clk";
|
||||
RVL_ALIAS "i_sys_clk" "i_sys_clk";
|
||||
BLOCK RESETPATHS ;
|
||||
BLOCK ASYNCPATHS ;
|
||||
LOCATE COMP "i_sys_clk" SITE "B9" ;
|
||||
LOCATE COMP "i_rst_n" SITE "Y14" ;
|
||||
LOCATE COMP "i_sclk" SITE "AA10" ;
|
||||
LOCATE COMP "i_cs" SITE "AB11" ;
|
||||
LOCATE COMP "i_mosi" SITE "AB12" ;
|
||||
LOCATE COMP "o_miso" SITE "AA14" ;
|
||||
IOBUF PORT "i_cs" IO_TYPE=LVCMOS33 ;
|
||||
IOBUF PORT "i_mosi" IO_TYPE=LVCMOS33 ;
|
||||
IOBUF PORT "i_rst_n" IO_TYPE=LVCMOS33 ;
|
||||
IOBUF PORT "i_sclk" IO_TYPE=LVCMOS33 ;
|
||||
IOBUF PORT "o_miso" IO_TYPE=LVCMOS33 PULLMODE=NONE DRIVE=8 ;
|
||||
IOBUF PORT "o_rvaild" IO_TYPE=LVCMOS33 PULLMODE=NONE ;
|
||||
IOBUF PORT "o_wready" IO_TYPE=LVCMOS33 PULLMODE=NONE ;
|
||||
IOBUF PORT "i_sys_clk" DRIVE=NA IO_TYPE=LVCMOS33 SLEWRATE=NA PULLMODE=DOWN ;
|
||||
IOBUF PORT "o_err" IO_TYPE=LVCMOS33 ;
|
||||
LOCATE COMP "o_err" SITE "AB16" ;
|
||||
LOCATE COMP "o_PMU_RC[0]" SITE "V2" ;
|
||||
LOCATE COMP "o_PMU_RC[1]" SITE "N18" ;
|
||||
LOCATE COMP "o_PMU_RC[2]" SITE "P19" ;
|
||||
LOCATE COMP "o_PMU_RC[3]" SITE "P18" ;
|
||||
IOBUF PORT "o_PMU_RC[0]" IO_TYPE=LVCMOS33 ;
|
||||
IOBUF PORT "o_PMU_RC[1]" IO_TYPE=LVCMOS33 ;
|
||||
IOBUF PORT "o_PMU_RC[2]" IO_TYPE=LVCMOS33 ;
|
||||
IOBUF PORT "o_PMU_RC[3]" IO_TYPE=LVCMOS33 ;
|
||||
BLOCK JTAGPATHS ;
|
||||
@@ -0,0 +1,165 @@
|
||||
module Reg_file (
|
||||
input i_sys_clk,
|
||||
input i_rst_n,
|
||||
|
||||
// Bus Interface
|
||||
input i_wr_req,
|
||||
input i_wr,
|
||||
input [6:0] i_addr,
|
||||
input [23:0] i_wdata,
|
||||
|
||||
output [23:0] o_rdata,
|
||||
output o_rvalid,
|
||||
output o_busy,
|
||||
output o_err,
|
||||
|
||||
// Controller Interface
|
||||
input i_con_done, // 1=IDLE/DONE, 0=BUSY
|
||||
output o_exec,
|
||||
|
||||
// Direct Register Outputs
|
||||
output [23:0] o_freq1,
|
||||
output [23:0] o_freq2,
|
||||
output [23:0] o_freq3,
|
||||
output [23:0] o_freq4
|
||||
);
|
||||
|
||||
// --- Parameters ---
|
||||
localparam REG_COUNT = 16;
|
||||
localparam [23:0]
|
||||
IDENT = 24'h800000|| 12'b0001_0000_0000, //CPLD3==1,version=1.0.0
|
||||
STATE_INIT = 24'h800000;
|
||||
|
||||
// State Machine Definition
|
||||
localparam IDLE = 4'd0;
|
||||
localparam BUSY = 4'd1;
|
||||
localparam EXEC_ACK = 4'd2; // Wait for controller to go BUSY (Done=0)
|
||||
localparam EXEC_WAIT = 4'd3; // Wait for controller to go DONE (Done=1)
|
||||
|
||||
// --- Internal Signals ---
|
||||
reg [3:0] state;
|
||||
reg [23:0] regtable [0:REG_COUNT - 1];
|
||||
reg [23:0] rdata_reg;
|
||||
|
||||
reg busy_flag;
|
||||
reg err_flag;
|
||||
reg rvalid_flag;
|
||||
|
||||
integer i;
|
||||
|
||||
// Mapping Control Bits
|
||||
wire exec_bit = regtable[1][0];
|
||||
|
||||
always @(posedge i_sys_clk or negedge i_rst_n) begin
|
||||
if (!i_rst_n) begin
|
||||
for (i = 0; i < REG_COUNT; i = i + 1) begin
|
||||
regtable[i] <= 24'h0;
|
||||
end
|
||||
regtable[0] <= IDENT;
|
||||
regtable[1] <= STATE_INIT;
|
||||
|
||||
rvalid_flag <= 1'b0;
|
||||
busy_flag <= 1'b0;
|
||||
err_flag <= 1'b0;
|
||||
state <= IDLE;
|
||||
end
|
||||
else begin
|
||||
case (state)
|
||||
IDLE: begin
|
||||
rvalid_flag <= 1'b0;
|
||||
err_flag <= 1'b0;
|
||||
|
||||
// Priority Check: Did we crash/reset while EXEC bit was still 1?
|
||||
if (exec_bit == 1'b1) begin
|
||||
state <= EXEC_ACK;
|
||||
busy_flag <= 1'b1;
|
||||
end
|
||||
else if (i_wr_req == 1'b1) begin
|
||||
busy_flag <= 1'b1;
|
||||
state <= BUSY;
|
||||
|
||||
// Addr Sanity Check
|
||||
if ((i_wr && (i_addr == 'd0 || i_addr >= REG_COUNT)) ||
|
||||
(!i_wr && (i_addr >= REG_COUNT)))
|
||||
begin
|
||||
err_flag <= 1'b1;
|
||||
end
|
||||
end
|
||||
else begin
|
||||
busy_flag <= 1'b0;
|
||||
end
|
||||
end
|
||||
|
||||
BUSY: begin
|
||||
if (err_flag) begin
|
||||
state <= IDLE;
|
||||
end
|
||||
else begin
|
||||
if (i_wr == 1'b1) begin // --- WRITE ---
|
||||
if (exec_bit == 1'b1) begin
|
||||
// Cannot write if Controller is already running
|
||||
err_flag <= 1'b1;
|
||||
state <= IDLE;
|
||||
end
|
||||
else begin
|
||||
regtable[i_addr] <= i_wdata;
|
||||
|
||||
// Check if this write is a "Start Command"
|
||||
if (i_addr == 7'd1 && i_wdata[0] == 1'b1) begin
|
||||
// Go to Handshake Start
|
||||
state <= EXEC_ACK;
|
||||
end else begin
|
||||
state <= IDLE;
|
||||
end
|
||||
end
|
||||
end
|
||||
else begin // --- READ ---
|
||||
rdata_reg <= regtable[i_addr];
|
||||
rvalid_flag <= 1'b1;
|
||||
state <= IDLE;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// --- EXEC PHASE 1: ACK ---
|
||||
// Wait for Controller to register the command and pull 'done' LOW (Busy)
|
||||
EXEC_ACK: begin
|
||||
busy_flag <= 1'b1;
|
||||
state <= EXEC_WAIT;
|
||||
// Optional: Timeout counter here to prevent hanging if Controller is dead
|
||||
end
|
||||
|
||||
// --- EXEC PHASE 2: WAIT ---
|
||||
// Now wait for Controller to finish and pull 'done' HIGH (Idle/Ready)
|
||||
EXEC_WAIT: begin
|
||||
busy_flag <= 1'b1;
|
||||
if (i_con_done == 1'b1) begin
|
||||
// 1. Clear the Exec bit (Auto-Clear)
|
||||
// 2. Set the Ready bit (Bit 23) if you wish
|
||||
regtable[1] <= {1'b1, regtable[1][22:1], 1'b0};
|
||||
|
||||
busy_flag <= 1'b0;
|
||||
state <= IDLE;
|
||||
end
|
||||
end
|
||||
|
||||
default: state <= IDLE;
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
assign o_rvalid = rvalid_flag;
|
||||
assign o_rdata = rdata_reg;
|
||||
assign o_busy = busy_flag;
|
||||
assign o_err = err_flag;
|
||||
|
||||
// Output the control bit to the controller
|
||||
// This stays HIGH during both EXEC_ACK and EXEC_WAIT
|
||||
assign o_exec = exec_bit;
|
||||
|
||||
assign o_freq1 = regtable[2];
|
||||
assign o_freq2 = regtable[3];
|
||||
assign o_freq3 = regtable[4];
|
||||
assign o_freq4 = regtable[5];
|
||||
|
||||
endmodule
|
||||
@@ -0,0 +1,98 @@
|
||||
module RelayConTop (
|
||||
input i_sys_clk,
|
||||
input i_rst_n,
|
||||
|
||||
input i_sclk,
|
||||
input i_mosi,
|
||||
input i_cs,
|
||||
output o_miso,
|
||||
output o_rvaild,
|
||||
input i_rready,
|
||||
input i_wvaild,
|
||||
output o_wready,
|
||||
output o_err,
|
||||
output o_con_done,
|
||||
output [3:0]o_PMU_RC
|
||||
);
|
||||
|
||||
wire [3:0]PMU_RC ;
|
||||
|
||||
|
||||
wire [23:0]r_data ;
|
||||
wire [23:0]w_data ;
|
||||
wire [6:0]reg_addr ;
|
||||
|
||||
wire cmd_vaild;
|
||||
wire reg_busy;
|
||||
wire wr_flag; //1=write,0=read
|
||||
wire bus_err_flag;
|
||||
wire reg_err_flag;
|
||||
wire cpld_err_flag;
|
||||
|
||||
wire con_exec;
|
||||
wire [23:0]freq1_relay ;
|
||||
wire [23:0]freq2_relay ;
|
||||
wire [23:0]freq3_relay ;
|
||||
wire [23:0]freq4_relay ;
|
||||
wire con_rvaild;
|
||||
|
||||
wire con_done;
|
||||
|
||||
BUS_Con Bus_Con_3(
|
||||
.i_sys_clk(i_sys_clk),
|
||||
.i_rst_n(i_rst_n),
|
||||
.i_sclk(i_sclk),
|
||||
.i_mosi(i_mosi),
|
||||
.i_cs(i_cs),
|
||||
.i_rvalid(con_rvalid),
|
||||
.i_wvalid(i_wvalid),
|
||||
.i_reg_busy(reg_busy),
|
||||
.i_rdata(r_data),
|
||||
.o_cmd_valid(cmd_vaild),
|
||||
.o_wr(wr_flag),
|
||||
.o_miso(o_miso),
|
||||
.o_rvalid(o_rvalid),
|
||||
.o_wready(o_wready),
|
||||
.o_data(w_data),
|
||||
.o_addr(reg_addr),
|
||||
.o_err(bus_err_flag)
|
||||
);
|
||||
|
||||
Reg_file CPLD_Reg_3(
|
||||
.i_sys_clk(i_sys_clk),
|
||||
.i_rst_n(i_rst_n),
|
||||
.i_wr_req(cmd_vaild),
|
||||
.i_wr(wr_flag),
|
||||
.i_addr(reg_addr),
|
||||
.i_wdata(w_data),
|
||||
.i_con_done(con_done), //Controller Exec Done
|
||||
.o_freq1(freq1_relay), //Freq_Slot1
|
||||
.o_freq2(freq2_relay), //Freq_Slot2
|
||||
.o_freq3(freq3_relay), //Freq_Slot3
|
||||
.o_freq4(freq4_relay), //Freq_Slot4
|
||||
.o_rvalid(con_rvalid),
|
||||
.o_rdata(r_data),
|
||||
.o_exec(con_exec), //Exec cmd
|
||||
.o_busy(reg_busy),
|
||||
.o_err(reg_err_flag)
|
||||
);
|
||||
|
||||
CPLD_Con CPLD_Con_3(
|
||||
.i_sys_clk(i_sys_clk),
|
||||
.i_rst_n(i_rst_n),
|
||||
.i_con_exec(con_exec),
|
||||
.i_freq_relay1(freq1_relay),
|
||||
.i_freq_relay2(freq2_relay),
|
||||
.i_freq_relay3(freq3_relay),
|
||||
.i_freq_relay4(freq4_relay),
|
||||
.o_con_done(con_done),
|
||||
.o_PMU_RC(PMU_RC),
|
||||
.o_err(cpld_err_flag)
|
||||
);
|
||||
|
||||
assign o_con_done = con_done;
|
||||
assign o_PMU_RC = PMU_RC;
|
||||
|
||||
assign o_err = bus_err_flag || reg_err_flag ||cpld_err_flag;
|
||||
|
||||
endmodule
|
||||
@@ -0,0 +1,310 @@
|
||||
`timescale 1ns/1ps
|
||||
|
||||
module tb_RelayConTop;
|
||||
|
||||
// 时钟和复位
|
||||
reg i_sys_clk;
|
||||
reg i_rst_n;
|
||||
|
||||
// SPI接口
|
||||
reg i_sclk;
|
||||
reg i_mosi;
|
||||
reg i_cs;
|
||||
// wire o_miso;
|
||||
|
||||
// 流控制接口
|
||||
// wire o_rvaild;
|
||||
// reg i_rready;
|
||||
// reg i_wvaild;
|
||||
// wire o_wready;
|
||||
wire o_err;
|
||||
|
||||
// 继电器控制输出
|
||||
wire [7:0] o_RC_F;
|
||||
wire [15:0] o_RC_S;
|
||||
wire [31:0] o_RC_T;
|
||||
|
||||
// 测试变量
|
||||
reg [31:0] spi_data;
|
||||
integer test_pass;
|
||||
integer test_fail;
|
||||
|
||||
// 实例化被测模块
|
||||
RelayConTop DUT (
|
||||
.i_sys_clk(i_sys_clk),
|
||||
.i_rst_n(i_rst_n),
|
||||
.i_sclk(i_sclk),
|
||||
.i_mosi(i_mosi),
|
||||
.i_cs(i_cs),
|
||||
// .o_miso(o_miso),
|
||||
// .o_rvaild(o_rvaild),
|
||||
// .i_rready(i_rready),
|
||||
// .i_wvaild(i_wvaild),
|
||||
// .o_wready(o_wready),
|
||||
.o_err(o_err),
|
||||
.o_RC_F(o_RC_F),
|
||||
.o_RC_S(o_RC_S),
|
||||
.o_RC_T(o_RC_T)
|
||||
);
|
||||
|
||||
// 时钟生成
|
||||
initial begin
|
||||
i_sys_clk = 0;
|
||||
forever #5 i_sys_clk = ~i_sys_clk; // 20MHz系统时钟
|
||||
end
|
||||
|
||||
// SPI时钟生成(比系统时钟慢)
|
||||
initial begin
|
||||
i_sclk = 0;
|
||||
forever #50 i_sclk = ~i_sclk; // 2MHz SPI时钟
|
||||
end
|
||||
|
||||
// 主测试流程
|
||||
initial begin
|
||||
// 初始化
|
||||
initialize();
|
||||
|
||||
// 测试计数器
|
||||
test_pass = 0;
|
||||
test_fail = 0;
|
||||
|
||||
$display("=== CPLD2 Controller Test Start ===");
|
||||
|
||||
// 测试1: 复位后寄存器读取
|
||||
test_reset_registers();
|
||||
|
||||
|
||||
// 测试2: 寄存器写入和读取
|
||||
test_register_write_read();
|
||||
|
||||
// 测试3: EXEC命令执行测试
|
||||
test_exec_command();
|
||||
|
||||
// 测试4: 错误条件测试
|
||||
test_error_conditions();
|
||||
|
||||
// 测试5: SPI连续传输测试
|
||||
test_spi_continuous();
|
||||
|
||||
// 测试6: 边界条件测试
|
||||
test_boundary_conditions();
|
||||
|
||||
// 总结
|
||||
$display("=== Test Done ===");
|
||||
$display("PASS: %0d", test_pass);
|
||||
$display("Failed: %0d", test_fail);
|
||||
|
||||
if (test_fail == 0) begin
|
||||
$display("*** ALL TEST PASSED! ***");
|
||||
end else begin
|
||||
$display("*** TEST FAILED FOUND!! CHECK DESIGN ***");
|
||||
end
|
||||
|
||||
#1000 $finish;
|
||||
end
|
||||
|
||||
// 初始化任务
|
||||
task initialize;
|
||||
begin
|
||||
i_rst_n = 1;
|
||||
i_cs = 1;
|
||||
i_mosi = 0;
|
||||
#100;
|
||||
i_rst_n = 0;
|
||||
#200;
|
||||
i_rst_n = 1;
|
||||
i_cs = 1;
|
||||
$display("Initialize DONE!");
|
||||
end
|
||||
endtask
|
||||
|
||||
// SPI发送任务
|
||||
task spi_send;
|
||||
input [31:0] data;
|
||||
integer i;
|
||||
begin
|
||||
#50;
|
||||
i_cs = 0; // 片选有效
|
||||
|
||||
for (i = 31; i >= 0 ; i--) begin
|
||||
#50; // 在SCLK上升沿前设置数据
|
||||
i_mosi = data[i];
|
||||
#50; // 等待SCLK上升沿
|
||||
end
|
||||
#50
|
||||
i_cs = 1; // 片选无效
|
||||
#200;
|
||||
end
|
||||
endtask
|
||||
|
||||
// 测试1: 复位后寄存器读取
|
||||
task test_reset_registers;
|
||||
begin
|
||||
$display("--- TEST1: REG READ AFTER RST ---");
|
||||
// 读取芯片ID寄存器 (地址0)
|
||||
spi_data = {1'b1,23'h0, 1'b0,7'h0}; // 读操作,地址0,TEST
|
||||
spi_send(spi_data);
|
||||
|
||||
// 检查返回值(应该在MISO上看到0x400000)
|
||||
#1000;
|
||||
check_result(1, "CPLD READ ID");
|
||||
end
|
||||
endtask
|
||||
|
||||
// 测试2: 寄存器写入和读取
|
||||
task test_register_write_read;
|
||||
begin
|
||||
$display("--- TEST2: REG READ & WRITE ---");
|
||||
|
||||
// 写入频率槽1寄存器 (地址2)
|
||||
spi_data = {24'h123456,1'b1,7'h2}; // 写操作,地址2,数据0x123456
|
||||
spi_send(spi_data);
|
||||
#500;
|
||||
|
||||
// 读取频率槽1寄存器验证
|
||||
spi_data = {24'h0, 1'b0, 7'h2}; // 读操作,地址2
|
||||
spi_send(spi_data);
|
||||
#500;
|
||||
|
||||
check_result(1, "REG READ & WRITE");
|
||||
end
|
||||
endtask
|
||||
|
||||
// 测试3: EXEC命令执行测试
|
||||
task test_exec_command;
|
||||
begin
|
||||
$display("--- TEST3: EXEC TEST ---");
|
||||
|
||||
// 设置EXEC位 (地址1的bit0)
|
||||
spi_data = {24'h000001, 1'b1, 7'h1}; // 写操作,地址1,设置EXEC位
|
||||
spi_send(spi_data);
|
||||
#1000;
|
||||
|
||||
check_result(1, "EXEC TEST");
|
||||
end
|
||||
endtask
|
||||
|
||||
// 测试4: 错误条件测试
|
||||
task test_error_conditions;
|
||||
begin
|
||||
$display("--- 测试4: ERR TEST ---");
|
||||
|
||||
// 测试4.1: 写入只读寄存器 (地址0)
|
||||
spi_data = {24'hDEADBE,1'b1, 7'h0 }; // 尝试写入只读寄存器
|
||||
spi_send(spi_data);
|
||||
#500;
|
||||
|
||||
// 测试4.2: 访问超出范围的地址
|
||||
spi_data = {24'h0, 1'b0, 7'h20}; // 读取地址32(超出范围)
|
||||
spi_send(spi_data);
|
||||
#500;
|
||||
|
||||
check_result(1, "ERR TEST");
|
||||
end
|
||||
endtask
|
||||
|
||||
// 测试5: SPI连续传输测试
|
||||
task test_spi_continuous;
|
||||
begin
|
||||
$display("--- 测试5: SPI BATCH READ&WRITE ---");
|
||||
|
||||
// 连续写入多个寄存器
|
||||
spi_data = {24'h111111, 7'h2, 1'b1};
|
||||
spi_send(spi_data);
|
||||
#300;
|
||||
|
||||
spi_data = {24'h222222, 7'h3, 1'b1};
|
||||
spi_send(spi_data);
|
||||
#300;
|
||||
|
||||
spi_data = {24'h333333, 7'h4, 1'b1};
|
||||
spi_send(spi_data);
|
||||
#300;
|
||||
|
||||
// 连续读取验证
|
||||
spi_data = {24'h0, 7'h2, 1'b0};
|
||||
spi_send(spi_data);
|
||||
#300;
|
||||
|
||||
spi_data = {24'h0, 7'h3, 1'b0};
|
||||
spi_send(spi_data);
|
||||
#300;
|
||||
|
||||
spi_data = {24'h0, 7'h4, 1'b0};
|
||||
spi_send(spi_data);
|
||||
#300;
|
||||
|
||||
check_result(1, "SPI BATCH READ&WRITE");
|
||||
end
|
||||
endtask
|
||||
|
||||
// 测试6: 边界条件测试
|
||||
task test_boundary_conditions;
|
||||
begin
|
||||
$display("--- TEST6: EDGE CASE TEST ---");
|
||||
|
||||
// 测试6.1: 复位期间的SPI访问
|
||||
i_rst_n = 0;
|
||||
spi_data = {24'h0, 7'h1, 1'b0};
|
||||
spi_send(spi_data);
|
||||
#200;
|
||||
i_rst_n = 1;
|
||||
#500;
|
||||
|
||||
// 测试6.2: CS信号异常
|
||||
i_cs = 0;
|
||||
#50;
|
||||
i_cs = 1; // 短暂CS脉冲
|
||||
#50;
|
||||
i_cs = 0;
|
||||
#1000;
|
||||
i_cs = 1;
|
||||
#500;
|
||||
|
||||
check_result(1, "EDGE CASE TEST");
|
||||
end
|
||||
endtask
|
||||
|
||||
// 结果检查任务
|
||||
task check_result;
|
||||
input expected;
|
||||
input [120:1] test_name; // 字符数组存储测试名称
|
||||
begin
|
||||
if (expected) begin
|
||||
test_pass = test_pass + 1;
|
||||
$display("TEST %s - PASSED", test_name);
|
||||
end else begin
|
||||
test_fail = test_fail + 1;
|
||||
$display("TEST %s - FAILED", test_name);
|
||||
end
|
||||
end
|
||||
endtask
|
||||
|
||||
/*
|
||||
// 监控关键信号
|
||||
initial begin
|
||||
$display("TIME | CS | SCLK | MOSI | MISO | ERR | RC_CON");
|
||||
$display("-----|----|------|------|------|------|--------");
|
||||
forever begin
|
||||
#1000;
|
||||
$display("%4t | %b | %b | %b | %b | %b | F:%h S:%h T:%h",
|
||||
$time, i_cs, i_sclk, i_mosi, o_miso, o_err,
|
||||
o_RC_F, o_RC_S, o_RC_T);
|
||||
end
|
||||
end
|
||||
*/
|
||||
|
||||
// VCD文件生成(用于波形查看)
|
||||
initial begin
|
||||
$dumpfile("relay_con_top.vcd");
|
||||
$dumpvars(0, tb_RelayConTop);
|
||||
end
|
||||
|
||||
// 超时保护
|
||||
initial begin
|
||||
#5000000; // 5ms超时
|
||||
$display("!!! TEST TIMEOUT !!!");
|
||||
$finish;
|
||||
end
|
||||
|
||||
endmodule
|
||||
Reference in New Issue
Block a user