I'm developing a memory controller for asynchronous memory (as SRAM, MRAM, etc) and am facing some issue with properly constraining my design. I've prepared very simple design to depict my issue and attached it to the thread. Please keep in mind, that this is a modified chunk of a larger project.
Design description:
This simplifed design shows fetching data on input pads on every 20 MHz clock cycle. Faster clock, which frequency is 160 MHz, gives me resolution to latch
data_i on each 1/8 of 20 MHz clock cycle.
Data_i is latched on negative edge, when
latch_sr[5] == 1. In total, we have 2x 8-bit registers for data latch, 1x 8-bit shift register for selecting the position of when
data_i (changes asynchronous on input pads after 35 ns, relative to raising edge of
clk_20 and is stable for 50 ns) is latched in
data_latch register and two 1-bit registers for
clk_20 positive edge detection.
Clk_20 is sampled with
clk_160 and it’s positive edge will reset the
latch_sr shift register.
Clk_20 is main clock of the design and on the positive edge of the clock,
data_i must to be present on
data_o for further operations.
Problem description:
What worries me now is how to tell SmartTime with help of multicycle constraint (if this is the correct constraint), that
data_i (through data_latch) will be present on
data_o after cycle and a half (due to latching the data on negative edge of
clk_160). As far as I can see, there is no atribute in
set_multicycle_path for specifying clock domains. If I don’t apply any of the constraint for this path, SmartTime won’t take this path as critical and will assume that there are no timing violations, but in practice I’ve calculated all the routes, and it shouldn’t be OK.
In my main project, there is also a big chunk of combinatorial logic between
data_latch and
data_o registers, which also delays the data path for 2-4 ns. Should this be taken to constraints consideration also?
Is multicycle constraint for this path the correct approach? And if so, what is the correct definition of it?
I’m using:
Libero 11.8.2.4 (Classic constraint flow)
IGLOO2 M2GL050T-FG484I
Verilog code:
Code Verilog - [expand] |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
| module top_des(
clk_osc_i,
rst_i,
data_i,
data_o
);
input clk_osc_i, rst_i;
input [7:0] data_i;
output [7:0] data_o;
reg [7:0] latch_sr;
reg [7:0] data_latch;
reg [7:0] data_o;
// Internal PLL
ccc_gen ccc_gen_u
(
// Inputs
.CLK0_PAD(clk_osc_i),
// Outputs
.GL0(clk_20),
.GL1(clk_160),
.LOCK(ccc_lock)
);
reg r1, r2;
always @ (posedge clk_160) begin
r1 <= clk_20;
r2 <= r1;
end
assign pos_edge = r1 & !r2;
always @ (posedge clk_160 or negedge rst_i) begin
if(!rst_i || !ccc_lock) begin
latch_sr <= 8'd1;
end
else begin
if(pos_edge) begin
latch_sr <= 8'd1;
end
else begin
latch_sr <= {latch_sr[6:0], latch_sr[7]};
end
end
end
always @ (negedge clk_160 or negedge rst_i) begin
if(!rst_i || !ccc_lock) begin
data_latch <= 8'd0;
end
else begin
if(latch_sr[5]) begin
data_latch <= data_i;
end
end
end
always @ (posedge clk_20 or negedge rst_i) begin
if(!rst_i || !ccc_lock) begin
data_o <= 8'd0;
end
else begin
data_o <= data_latch;
end
end
endmodule |