module clk_rcfg_ctrl
(
input rst_n,
input clk,
input cpu_cmd,
input cpu_wr,
input [19:0] cpu_addr,
input [31:0] cpu_wdata,
output reg [31:0] cpu_rdata,
output reg cpu_rdata_vld
);
reg [10:0] s_axi_awaddr;
reg s_axi_awvalid;
wire s_axi_awready;
reg [31:0] s_axi_wdata;
reg [3:0] s_axi_wstrb;
reg s_axi_wvalid;
wire s_axi_wready;
wire [1:0] s_axi_bresp;
wire s_axi_bvalid;
reg s_axi_bready;
reg [10:0] s_axi_araddr;
reg s_axi_arvalid;
wire s_axi_arready;
wire [31:0] s_axi_rdata;
wire [1:0] s_axi_rresp;
wire s_axi_rvalid;
reg s_axi_rready;
always @ (posedge clk or negedge rst_n)
begin
if (rst_n == 1'b0)
begin
s_axi_awvalid <= 1'b0;
s_axi_wvalid <= 1'b0;
s_axi_wdata <= 32'd0;
s_axi_awaddr <= 11'd0;
s_axi_wstrb <= 4'hf;
s_axi_bready <= 1'b0;
end
else if (cpu_cmd == 1'b1 && cpu_wr == 1'b1)
begin
s_axi_awvalid <= 1'b1;
s_axi_wvalid <= 1'b1;
s_axi_wdata <= cpu_wdata;
s_axi_awaddr <= cpu_addr[10:0];
s_axi_wstrb <= 4'hf;
s_axi_bready <= 1'b0;
end
else if (s_axi_wready == 1'b1 && s_axi_awready == 1'b1)
s_axi_bready <= 1'b1;
else begin
s_axi_awvalid <= 1'b0;
s_axi_wvalid <= 1'b0;
s_axi_bready <= 1'b0;
end
end
always @ (posedge clk or negedge rst_n)
begin
if (rst_n == 1'b0)
begin
s_axi_arvalid <= 1'b0;
s_axi_rready <= 1'b0;
s_axi_araddr <= 11'd0;
cpu_rdata <= 32'd0;
cpu_rdata_vld <= 1'b0;
end
else if (cpu_cmd == 1'b1 && cpu_wr == 1'b0)
begin
s_axi_arvalid <= 1'b1;
s_axi_rready <= 1'b1;
s_axi_araddr <= cpu_addr[10:0];
cpu_rdata <= 32'd0;
cpu_rdata_vld <= 1'b0;
end
else if (s_axi_rvalid == 1'b1)
begin
s_axi_arvalid <= 1'b0;
s_axi_rready <= 1'b0;
s_axi_araddr <= 10'd0;
cpu_rdata <= s_axi_rdata;
cpu_rdata_vld <= 1'b1;
end
else
begin
cpu_rdata <= 32'd0;
cpu_rdata_vld <= 1'b0;
end
end
clk_recfg u_clk_recfg
(
.s_axi_aclk (clk ),
.s_axi_aresetn (rst_n ),
.s_axi_awaddr (s_axi_awaddr ),
.s_axi_awvalid (s_axi_awvalid ),
.s_axi_awready (s_axi_awready ),
.s_axi_wdata (s_axi_wdata ),
.s_axi_wstrb (s_axi_wstrb ),
.s_axi_wvalid (s_axi_wvalid ),
.s_axi_wready (s_axi_wready ),
.s_axi_bresp (s_axi_bresp ),
.s_axi_bvalid (s_axi_bvalid ),
.s_axi_bready (s_axi_bready ),
.s_axi_araddr (s_axi_araddr ),
.s_axi_arvalid (s_axi_arvalid ),
.s_axi_arready (s_axi_arready ),
.s_axi_rdata (s_axi_rdata ),
.s_axi_rresp (s_axi_rresp ),
.s_axi_rvalid (s_axi_rvalid ),
.s_axi_rready (s_axi_rready ),
.clk_out1 (),
.locked (),
.clk_in1 (clk )
);
endmodule
task cpu_rd(input [31:0] addr, output [31:0] rdata);
begin
@(posedge clk_100m);
cpu_cmd = 1'b1;
cpu_addr = addr;
cpu_wr_rd = 1'b0;
@(posedge clk_100m);
cpu_cmd = 1'b0;
@(posedge clk_100m);
wait(cpu_rdata_vld) rdata = cpu_rdata;
@(posedge clk_100m);
$display("%m: @%0t, rd addr:0x%8h 0x%8h",$time, addr, rdata);
end
endtask
task cpu_wr(input [31:0] addr,input [31:0] wdata);
begin
@(posedge clk_100m);
cpu_cmd = 1'b1;
cpu_addr = addr;
cpu_wr_rd = 1'b1;
cpu_wdata = wdata;
@(posedge clk_100m);
cpu_cmd = 1'b0;
cpu_wr_rd = 1'b0;
@(posedge clk_100m);
$display("%m: @%0t, write 0x%8h to 0x%8h",$time, wdata, addr);
end
endtask
`timescale 1ns/1ps
module tb_clk_drp;
parameter CLK_CY_100M = 10;
bit clk_100m;
always #(CLK_CY_100M/2) clk_100m = ~clk_100m;
//----------------------------------------------------------------------------//
//----------------------------------------------------------------------------//
bit rst_n;
initial
begin
rst_n = 1'b1;
#(CLK_CY_100M * 200) rst_n = 1'b0;
#(CLK_CY_100M * 100) rst_n = 1'b1;
end
//----------------------------------------------------------------------------//
reg [31:0] rd_dat;
reg cpu_cmd;
reg [31:0] cpu_addr;
reg [31:0] cpu_wdata;
reg cpu_wr_rd;
wire cpu_rdata_vld;
wire [31:0] cpu_rdata;
initial begin
rd_dat = 32'd0;
cpu_cmd = 1'b0;
cpu_addr = 32'd0;
cpu_wdata = 32'd0;
cpu_wr_rd = 1'b0;
end
`include "./cpu_wr_rd.v"
initial begin
repeat(500) @ (posedge clk_100m);
//read mmcm cfg
cpu_rd(32'h208, rd_dat);
repeat(30) @ (posedge clk_100m);
cpu_rd(32'h20c, rd_dat);
repeat(30) @ (posedge clk_100m);
cpu_rd(32'h210, rd_dat);
repeat(30) @ (posedge clk_100m);
//clk out1
cpu_rd(32'h214, rd_dat);
repeat(30) @ (posedge clk_100m);
cpu_rd(32'h218, rd_dat);
repeat(30) @ (posedge clk_100m);
cpu_rd(32'h21c, rd_dat);
repeat(30) @ (posedge clk_100m);
//write new cfg to mmcm
cpu_wr(32'h208, 32'h0004_000a);
repeat(30) @ (posedge clk_100m);
cpu_wr(32'h20c, 32'h0000_b1bc);
repeat(30) @ (posedge clk_100m);
cpu_wr(32'h210, 32'h0000_c350);
repeat(30) @ (posedge clk_100m);
cpu_wr(32'h214, 32'h0004_000a);
repeat(30) @ (posedge clk_100m);
// cpu_wr(32'h218, 32'h0001_5f90); //90
cpu_wr(32'h218, 32'h0004_1eb0); //270
repeat(30) @ (posedge clk_100m);
cpu_wr(32'h25c, 32'h0000_0003);
repeat(10) @ (posedge clk_100m);
//clk out0
cpu_rd(32'h208, rd_dat);
repeat(30) @ (posedge clk_100m);
cpu_rd(32'h20c, rd_dat);
repeat(30) @ (posedge clk_100m);
cpu_rd(32'h210, rd_dat);
repeat(30) @ (posedge clk_100m);
//clk out1
cpu_rd(32'h214, rd_dat);
repeat(30) @ (posedge clk_100m);
cpu_rd(32'h218, rd_dat);
repeat(30) @ (posedge clk_100m);
cpu_rd(32'h21c, rd_dat);
repeat(30) @ (posedge clk_100m);
repeat(2000) @ (posedge clk_100m);
$stop;
end
clk_rcfg_ctrl u_clk_rcfg_ctrl
(
.rst_n (rst_n ),
.clk (clk_100m ),
.cpu_cmd (cpu_cmd),
.cpu_wr (cpu_wr_rd),
.cpu_addr (cpu_addr),
.cpu_wdata (cpu_wdata),
.cpu_rdata (cpu_rdata),
.cpu_rdata_vld (cpu_rdata_vld)
);
endmodule