@@ -28,7 +28,8 @@ logic [15:0] data_read;
2828logic data_read_valid;
2929logic data_write_done;
3030
31- as4c4m16sa # (
31+ as4c4m16sa_controller # (
32+ .CLK_RATE (100_000_000 ),
3233 .SPEED_GRADE (7 ),
3334 .READ_BURST_LENGTH (8 ),
3435 .WRITE_BURST (1 ),
@@ -52,86 +53,144 @@ as4c4m16sa #(
5253 .dq (dq),
5354);
5455
55- logic [15 : 0 ] mipi_buffer [0 : 31 ];
56- logic [4 : 0 ] mipi_producer = 5'd0 ;
57- logic [4 : 0 ] mipi_consumer = 5'd0 ;
56+ logic [31 : 0 ] mipi_buff_data;
57+ logic [3 : 0 ] mipi_buff_used;
58+ logic mipi_buff_read = 1'b0 ;
59+ dcfifo mipi_dcfifo (
60+ .data ({ mipi_data[3 ], mipi_data[2 ], mipi_data[1 ], mipi_data[0 ]} ),
61+ .rdclk (sdram_clk),
62+ .rdreq (mipi_buff_read),
63+ .wrclk (mipi_clk),
64+ .wrreq (mipi_data_enable),
65+ .q (mipi_buff_data),
66+ .rdempty (),
67+ .wrusedw (),
68+ .aclr (),
69+ .eccstatus (),
70+ .rdfull (),
71+ .rdusedw (mipi_buff_used),
72+ .wrempty (),
73+ .wrfull ());
74+ defparam
75+ mipi_dcfifo.intended_device_family = " Cyclone 10 LP" ,
76+ mipi_dcfifo.lpm_numwords = 16 ,
77+ mipi_dcfifo.lpm_showahead = " ON" ,
78+ mipi_dcfifo.lpm_type = " dcfifo" ,
79+ mipi_dcfifo.lpm_width = 32 ,
80+ mipi_dcfifo.lpm_widthu = 4 ,
81+ mipi_dcfifo.overflow_checking = " ON" ,
82+ mipi_dcfifo.rdsync_delaypipe = 4 ,
83+ mipi_dcfifo.underflow_checking = " ON" ,
84+ mipi_dcfifo.use_eab = " ON" ,
85+ mipi_dcfifo.wrsync_delaypipe = 4 ;
5886
59- always @ (posedge mipi_clk)
60- begin
61- if (mipi_data_enable)
62- begin
63- mipi_buffer[mipi_producer] <= { mipi_data[0 ], mipi_data[1 ]} ;
64- mipi_buffer[mipi_producer + 1'd1 ] <= { mipi_data[2 ], mipi_data[3 ]} ;
65- mipi_producer <= mipi_producer + 5'd2 ;
66- end
67- end
68-
69-
70- logic [15 : 0 ] pixel_buffer [0 : 31 ];
71- logic [4 : 0 ] pixel_producer = 5'd0 ;
72- logic [4 : 0 ] pixel_consumer = 5'd0 ;
73- logic pixel_countup = 1'd0 ;
74- assign pixel = pixel_countup ? pixel_buffer[pixel_consumer][15 : 8 ] : pixel_buffer[pixel_consumer][7 : 0 ];
75-
76- always @ (posedge pixel_clk)
77- begin
78- if (pixel_enable)
79- begin
80- if (pixel_countup == 1'd1 )
81- pixel_consumer <= pixel_consumer + 1'd1 ;
82- pixel_countup <= ! pixel_countup;
83- end
84- end
8587
86- logic [4 : 0 ] mipi_diff;
87- assign mipi_diff = mipi_producer >= mipi_consumer ? mipi_producer - mipi_consumer : (~ 5'd0 - mipi_consumer) + mipi_producer;
88- logic [4 : 0 ] pixel_diff;
89- assign pixel_diff = pixel_producer >= pixel_consumer ? pixel_producer - pixel_consumer : (~ 5'd0 - pixel_consumer) + pixel_producer;
88+ logic [21 : 0 ] mipi_address = 22'd0 ;
89+ logic [21 : 0 ] pixel_address = 22'd0 ;
90+ logic [2 : 0 ] sdram_countup = 3'd0 ;
9091
91- logic [17 : 0 ] mipi_address;
92- logic [17 : 0 ] pixel_address;
92+ logic pixel_buff_write = 1'b0 ;
93+ logic [15 : 0 ] pixel_buff_data = 16'd0 ;
94+ logic [4 : 0 ] pixel_buff_used;
9395
94- logic [2 : 0 ] sdram_countup = 3'd0 ;
9596always @ (posedge sdram_clk)
9697begin
98+ mipi_buff_read <= 1'b0 ;
99+ pixel_buff_write <= 1'b0 ;
100+ pixel_buff_data <= 16'dx ;
97101 if (command == 2'd0 )
98102 begin
99- if (pixel_diff < 5'd8 ) // Read is approaching starvation
103+ if (! pixel_buff_used[ 4 ] ) // Read burst possible
100104 begin
101105 command <= 2'd2 ;
106+ data_write <= 16'dx ;
102107 data_address <= pixel_address;
108+ sdram_countup <= 1'd0 ;
103109 end
104- else if (mipi_diff >= 5'd15 ) // Ready to write
110+ else if (mipi_buff_used[ 3 ] ) // Write burst possible
105111 begin
106112 command <= 2'd1 ;
107- data_write <= mipi_buffer[mipi_consumer ];
113+ data_write <= mipi_buff_data[ 15 : 0 ];
108114 data_address <= mipi_address;
109- mipi_consumer <= mipi_consumer + 1'd1 ;
110- sdram_countup <= sdram_countup + 1'd1 ;
115+ sdram_countup <= 1'd1 ;
116+ end
117+ else // Idle
118+ begin
119+ command <= 2'd0 ;
120+ data_write <= 16'dx ;
121+ data_address <= 22'dx ;
122+ sdram_countup <= 3'dx ;
111123 end
112124 end
113125 else if (command == 2'd2 && data_read_valid)
114126 begin
115- pixel_buffer[pixel_producer] <= data_read;
116- pixel_producer <= pixel_producer + 1'd1 ;
127+ pixel_buff_data <= data_read;
128+ pixel_buff_write <= 1'b1 ;
117129 sdram_countup <= sdram_countup + 1'd1 ;
118130 if (sdram_countup == 3'd7 ) // Last read
119131 begin
120132 command <= 2'd0 ;
121- pixel_address <= pixel_address + 8 'd8 == 18 '(VIDEO_END ) ? 18 'd0 : pixel_address + 18 'd8 ;
133+ pixel_address <= pixel_address + 22 'd8 == 22 '(VIDEO_END ) ? 22 'd0 : pixel_address + 22 'd8 ;
122134 end
123135 end
124136 else if (command == 2'd1 && data_write_done)
125137 begin
126- data_write <= mipi_buffer[mipi_consumer];
127- mipi_consumer <= mipi_consumer + 1'd1 ;
128138 sdram_countup <= sdram_countup + 1'd1 ;
139+ if (sdram_countup[0 ])
140+ begin
141+ data_write <= mipi_buff_data[31 : 16 ];
142+ mipi_buff_read <= 1'b1 ;
143+ end
144+ else
145+ begin
146+ data_write <= mipi_buff_data[15 : 0 ];
147+ mipi_buff_read <= 1'b0 ;
148+ end
149+
129150 if (sdram_countup == 3'd7 ) // Last write
130151 begin
131152 command <= 2'd0 ;
132- mipi_address <= mipi_address + 8 'd8 == 18 '(VIDEO_END ) ? 18 'd0 : mipi_address + 18 'd8 ;
153+ mipi_address <= mipi_address + 22 'd8 == 22 '(VIDEO_END ) ? 22 'd0 : mipi_address + 22 'd8 ;
133154 end
134155 end
135156end
136157
158+
159+ logic [15 : 0 ] internal_pixel;
160+ logic pixel_countup = 1'd0 ;
161+ assign pixel = pixel_countup ? internal_pixel[15 : 8 ] : internal_pixel[7 : 0 ];
162+ always @ (posedge pixel_clk)
163+ begin
164+ if (pixel_enable)
165+ pixel_countup <= ! pixel_countup;
166+ end
167+
168+ dcfifo pixel_dcfifo (
169+ .data (pixel_buff_data),
170+ .rdclk (pixel_clk),
171+ .rdreq (pixel_enable && pixel_countup == 1'b1 ),
172+ .wrclk (sdram_clk),
173+ .wrreq (pixel_buff_write),
174+ .q (internal_pixel),
175+ .rdempty (),
176+ .wrusedw (pixel_buff_used),
177+ .aclr (),
178+ .eccstatus (),
179+ .rdfull (),
180+ .rdusedw (),
181+ .wrempty (),
182+ .wrfull ());
183+ defparam
184+ pixel_dcfifo.intended_device_family = " Cyclone 10 LP" ,
185+ pixel_dcfifo.lpm_numwords = 32 ,
186+ pixel_dcfifo.lpm_showahead = " ON" ,
187+ pixel_dcfifo.lpm_type = " dcfifo" ,
188+ pixel_dcfifo.lpm_width = 16 ,
189+ pixel_dcfifo.lpm_widthu = 5 ,
190+ pixel_dcfifo.overflow_checking = " ON" ,
191+ pixel_dcfifo.rdsync_delaypipe = 4 ,
192+ pixel_dcfifo.underflow_checking = " ON" ,
193+ pixel_dcfifo.use_eab = " ON" ,
194+ pixel_dcfifo.wrsync_delaypipe = 4 ;
195+
137196endmodule
0 commit comments