Skip to content

Commit 5fb4f99

Browse files
BROsandrHepoH3
andauthored
ЛР13. Обновление vga (#92)
* Fix(vga):Испр-ие чтения из char_tiff * Ref(vgachargen):Испр-ие коммента к clk100m_i * ЛР13. Добавление примечания насчет синхронного чтения в vga_sb_ctrl --------- Co-authored-by: Andrei Solodovnikov <[email protected]>
1 parent a4294c9 commit 5fb4f99

File tree

5 files changed

+92
-116
lines changed

5 files changed

+92
-116
lines changed

Labs/13. Peripheral units/README.md

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -744,8 +744,7 @@ module vgachargen (
744744
* firmware/mem_files/lab_13_ps2_vga_instr.mem — этим файлом необходимо проинициализировать память инструкций
745745
* firmware/mem_files/lab_13_ps2ascii_data.mem — этим файлом необходимо проинициализировать память данных
746746
* firmware/mem_files/lab_13_vga_ch_map.mem
747-
* firmware/mem_files/lab_13_vga_ch_t_ro.mem
748-
* firmware/mem_files/lab_13_vga_ch_t_rw.mem
747+
* firmware/mem_files/lab_13_vga_ch_t.mem
749748
* firmware/mem_files/lab_13_vga_col_map.mem
750749

751750
Вам необходимо добавить в проект все эти файлы.
@@ -802,9 +801,12 @@ module vga_sb_ctrl (
802801

803802
Оба эти сигнала мультиплексируются / демультиплексируются с помощью одного и того же управляющего сигнала: `addr_i[13:12]` в соответствии с диапазонами адресов (рис. 4):
804803

805-
* `addr_i[13:12] == 2'b00` — сигнал `write_enable_i` поступает на вход `char_map_we_i`, выход `char_map_rdata_o` записывается в выходной регистр `read_data_o`;
806-
* `addr_i[13:12] == 2'b01` — сигнал `write_enable_i` поступает на вход `col_map_we_i`, выход `col_map_rdata_o` записывается в выходной регистр `read_data_o`;
807-
* `addr_i[13:12] == 2'b10` — сигнал `write_enable_i` поступает на вход `char_tiff_we_i`, выход `char_tiff_rdata_o` записывается в выходной регистр `read_data_o`.
804+
- `addr_i[13:12] == 2'b00` — сигнал `write_enable_i` поступает на вход `char_map_we_i`, выход `char_map_rdata_o` подается на выход `read_data_o`;
805+
- `addr_i[13:12] == 2'b01` — сигнал `write_enable_i` поступает на вход `col_map_we_i`, выход `col_map_rdata_o` подается на выход `read_data_o`;
806+
- `addr_i[13:12] == 2'b10` — сигнал `write_enable_i` поступает на вход `char_tiff_we_i`, выход `char_tiff_rdata_o` подается на выход `read_data_o`.
807+
808+
> [!Important]
809+
> Обратите внимание на то что, контроллер vga является единственным контроллером, для которого не нужно реализовывать регистр перед выходом read_data_o для реализации синхронного чтения. Данная особенность обусловленна тем, что внутри модуля `vgachargen` уже находится блочная память с синхронным портом на чтение. Добавление еще одного регистра приведет к тому, данные будут "опаздывать" на один такт. Таким образом, данные на выход `read_data_o` необходимо подавать с помощью чисто комбинационной логики.
808810
809811
## Список использованной литературы
810812

Labs/13. Peripheral units/firmware/mem_files/lab_13_vga_ch_map.mem

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -597,3 +597,4 @@
597597
53525150
598598
57565554
599599
5b5a5958
600+
5f5e5d5c

Labs/13. Peripheral units/firmware/mem_files/lab_13_vga_ch_t_rw.mem

Lines changed: 0 additions & 33 deletions
This file was deleted.

Labs/13. Peripheral units/peripheral modules/vgachargen.sv

Lines changed: 84 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,12 @@ module vgachargen
1212
import vgachargen_pkg::*;
1313
#(
1414
parameter int unsigned CLK_FACTOR_25M = 100 / 25,
15-
parameter CH_T_RO_INIT_FILE_NAME = "lab_13_vga_ch_t_ro.mem",
16-
parameter bit CH_T_RO_INIT_FILE_IS_BIN = 1,
17-
parameter CH_T_RW_INIT_FILE_NAME = "lab_13_vga_ch_t_rw.mem",
18-
parameter bit CH_T_RW_INIT_FILE_IS_BIN = 1,
15+
parameter CH_T_INIT_FILE_NAME = "lab_13_vga_ch_t.mem",
16+
parameter bit CH_T_INIT_FILE_IS_BIN = 1'b1,
1917
parameter CH_MAP_INIT_FILE_NAME = "lab_13_vga_ch_map.mem",
20-
parameter bit CH_MAP_INIT_FILE_IS_BIN = 0,
18+
parameter bit CH_MAP_INIT_FILE_IS_BIN = 1'b0,
2119
parameter COL_MAP_INIT_FILE_NAME = "lab_13_vga_col_map.mem",
22-
parameter bit COL_MAP_INIT_FILE_IS_BIN = 0
20+
parameter bit COL_MAP_INIT_FILE_IS_BIN = 1'b0
2321
) (
2422
input logic clk_i, // системный синхроимпульс
2523
input logic clk100m_i, // клок с частотой 100МГц
@@ -58,13 +56,20 @@ module vgachargen
5856
output logic vga_hs_o, // линия горизонтальной синхронизации vga
5957
output logic vga_vs_o // линия вертикальной синхронизации vga
6058
);
59+
logic vga_clk_i;
60+
assign vga_clk_i = clk100m_i;
61+
62+
if (CLK_FACTOR_25M == 0 || CLK_FACTOR_25M > 4) error_unsupported_factor error_unsupported_factor ();
6163

6264
logic [3:0] char_map_be_gated;
6365
assign char_map_be_gated = char_map_be_i & {4{char_map_we_i}};
6466

6567
logic [3:0] col_map_be_gated;
6668
assign col_map_be_gated = col_map_be_i & {4{col_map_we_i}};
6769

70+
logic [3:0] char_tiff_be_gated;
71+
assign char_tiff_be_gated = char_tiff_be_i & {4{char_tiff_we_i}};
72+
6873
logic arstn_i;
6974
assign arstn_i = ~rst_i;
7075

@@ -78,7 +83,7 @@ module vgachargen
7883
.DATA_WIDTH (1),
7984
.DELAY_BY (2)
8085
) pixel_enable_delay (
81-
.clk_i (clk100m_i),
86+
.clk_i (vga_clk_i),
8287
.arstn_i (arstn_i),
8388
.data_i (pixel_enable),
8489
.data_o (pixel_enable_delayed)
@@ -91,7 +96,7 @@ module vgachargen
9196
.DATA_WIDTH (1),
9297
.DELAY_BY (2)
9398
) vga_vs_delay (
94-
.clk_i (clk100m_i),
99+
.clk_i (vga_clk_i),
95100
.arstn_i (arstn_i),
96101
.data_i (vga_vs),
97102
.data_o (vga_vs_delayed)
@@ -104,7 +109,7 @@ module vgachargen
104109
.DATA_WIDTH (1),
105110
.DELAY_BY (2)
106111
) vga_hs_delay (
107-
.clk_i (clk100m_i),
112+
.clk_i (vga_clk_i),
108113
.arstn_i (arstn_i),
109114
.data_i (vga_hs),
110115
.data_o (vga_hs_delayed)
@@ -114,7 +119,7 @@ module vgachargen
114119
vga_block #(
115120
.CLK_FACTOR_25M (CLK_FACTOR_25M)
116121
) vga_block (
117-
.clk_i (clk100m_i),
122+
.clk_i (vga_clk_i),
118123
.arstn_i (arstn_i),
119124
.hcount_o (hcount_pixels),
120125
.vcount_o (vcount_pixels),
@@ -132,7 +137,7 @@ module vgachargen
132137
.DATA_WIDTH (BITMAP_ADDR_WIDTH),
133138
.DELAY_BY (2)
134139
) bitmap_delay (
135-
.clk_i (clk100m_i),
140+
.clk_i (vga_clk_i),
136141
.arstn_i (arstn_i),
137142
.data_i (bitmap_addr),
138143
.data_o (bitmap_addr_delayed)
@@ -145,20 +150,33 @@ module vgachargen
145150
.bitmap_addr_o (bitmap_addr)
146151
);
147152

153+
logic [1:0] ch_map_byte_select;
154+
logic [1:0] ch_map_byte_select_delayed;
155+
assign ch_map_byte_select = ch_map_addr_internal[1:0];
156+
157+
delay #(
158+
.DATA_WIDTH (2),
159+
.DELAY_BY (1)
160+
) ch_map_byte_select_delay (
161+
.clk_i (vga_clk_i),
162+
.arstn_i (arstn_i),
163+
.data_i (ch_map_byte_select),
164+
.data_o (ch_map_byte_select_delayed)
165+
);
148166

149-
logic [CH_T_ADDR_WIDTH:0] ch_t_addr_internal;
167+
logic [CH_T_ADDR_WIDTH-1:0] ch_t_addr_internal;
150168

151169
logic [3:0][7:0] ch_map_data_word;
152170

153-
assign ch_t_addr_internal = ch_map_data_word[ch_map_addr_internal[1:0]];
171+
assign ch_t_addr_internal = ch_map_data_word[ch_map_byte_select_delayed];
154172

155173
true_dual_port_rw_bram #(
156174
.INIT_FILE_NAME (CH_MAP_INIT_FILE_NAME),
157175
.INIT_FILE_IS_BIN (CH_MAP_INIT_FILE_IS_BIN),
158176
.ADDR_WIDTH (10)
159177
) ch_map (
160178
.clka_i (clk_i),
161-
.clkb_i (clk100m_i),
179+
.clkb_i (vga_clk_i),
162180
.addra_i (char_map_addr_i),
163181
.addrb_i (ch_map_addr_internal[$left(ch_map_addr_internal):2]),
164182
.wea_i (char_map_be_gated),
@@ -167,62 +185,68 @@ module vgachargen
167185
.doutb_o (ch_map_data_word)
168186
);
169187

170-
logic [CH_T_ADDR_WIDTH-1:0] ch_t_ro_addr_internal;
171-
assign ch_t_ro_addr_internal = ch_t_addr_internal[CH_T_ADDR_WIDTH-1:0];
172-
logic [CH_T_DATA_WIDTH-1:0] ch_t_ro_data_internal;
188+
logic [CH_T_DATA_WIDTH-1:0] ch_t_data_internal;
173189

174-
single_port_ro_bram #(
175-
.INIT_FILE_NAME (CH_T_RO_INIT_FILE_NAME),
176-
.INIT_FILE_IS_BIN (CH_T_RO_INIT_FILE_IS_BIN),
177-
.DATA_WIDTH (CH_T_DATA_WIDTH),
178-
.ADDR_WIDTH (CH_T_ADDR_WIDTH)
179-
) ch_t_ro (
180-
.clk_i (clk100m_i),
181-
.addr_i(ch_t_ro_addr_internal),
182-
.dout_o(ch_t_ro_data_internal)
183-
);
190+
logic [CH_T_ADDR_WIDTH-1:0] char_tiff_addr_128bit;
191+
assign char_tiff_addr_128bit = char_tiff_addr_i[$left(char_tiff_addr_i):2];
192+
logic [1:0] char_tiff_addr_offset_32bit;
193+
assign char_tiff_addr_offset_32bit = char_tiff_addr_i[1:0];
194+
195+
logic [3:0][3:0] char_tiff_wea;
196+
197+
always_comb begin : bin2onehot
198+
char_tiff_wea = '0;
199+
char_tiff_wea[char_tiff_addr_offset_32bit] = char_tiff_be_gated;
200+
end
201+
202+
logic [6:0] char_tiff_addr_offset_128bit;
203+
logic [6:0] char_tiff_addr_offset_128bit_ff;
204+
assign char_tiff_addr_offset_128bit = {char_tiff_addr_offset_32bit, 5'b00000};
205+
206+
logic [127:0] char_tiff_wdata_128bit;
207+
208+
always_comb begin
209+
char_tiff_wdata_128bit = '0;
210+
char_tiff_wdata_128bit[char_tiff_addr_offset_128bit+:32] = char_tiff_wdata_i;
211+
end
212+
213+
logic [127:0] char_tiff_rdata_128bit;
214+
215+
assign char_tiff_rdata_o = char_tiff_rdata_128bit[char_tiff_addr_offset_128bit_ff+:32];
184216

185-
logic [CH_T_ADDR_WIDTH-1:0] ch_t_rw_addr_internal;
186-
assign ch_t_rw_addr_internal = ch_t_ro_addr_internal;
187-
logic [CH_T_DATA_WIDTH-1:0] ch_t_rw_data_internal;
217+
always_ff @(posedge clk_i) begin
218+
char_tiff_addr_offset_128bit_ff <= char_tiff_addr_offset_128bit;
219+
end
188220

189221
true_dual_port_rw_bram #(
190-
.INIT_FILE_NAME (CH_T_RW_INIT_FILE_NAME),
191-
.INIT_FILE_IS_BIN (CH_T_RW_INIT_FILE_IS_BIN),
192-
.NUM_COLS (1),
193-
.COL_WIDTH (CH_T_DATA_WIDTH),
222+
.INIT_FILE_NAME (CH_T_INIT_FILE_NAME),
223+
.INIT_FILE_IS_BIN (CH_T_INIT_FILE_IS_BIN),
224+
.NUM_COLS (16),
225+
.COL_WIDTH (8),
194226
.ADDR_WIDTH (CH_T_ADDR_WIDTH)
195-
) ch_t_rw (
227+
) char_tiff (
196228
.clka_i (clk_i),
197-
.clkb_i (clk100m_i),
198-
// .addra_i (ch_t_rw_addr_i),
199-
.addra_i (),
200-
.addrb_i (ch_t_rw_addr_internal),
201-
// .wea_i (ch_t_rw_wen_i),
202-
.wea_i (),
203-
// .dina_i (ch_t_rw_data_i),
204-
.dina_i (),
205-
// .douta_o (ch_t_rw_data_o),
206-
.douta_o (),
207-
.doutb_o (ch_t_rw_data_internal)
229+
.clkb_i (vga_clk_i),
230+
.addra_i (char_tiff_addr_128bit),
231+
.addrb_i (ch_t_addr_internal),
232+
.wea_i (char_tiff_wea),
233+
.dina_i (char_tiff_wdata_128bit),
234+
.douta_o (char_tiff_rdata_128bit),
235+
.doutb_o (ch_t_data_internal)
208236
);
209237

210-
logic [CH_T_DATA_WIDTH-1:0] ch_t_data_internal;
211-
assign ch_t_data_internal = ch_t_addr_internal[CH_T_ADDR_WIDTH] ? ch_t_rw_data_internal
212-
: ch_t_ro_data_internal;
213-
214238
logic [7:0] col_map_data_internal;
215239
logic [7:0] col_map_data_internal_delayed;
216240

217241
logic [3:0][7:0] col_map_data_internal_word;
218242

219-
assign col_map_data_internal = col_map_data_internal_word[ch_map_addr_internal[1:0]];
243+
assign col_map_data_internal = col_map_data_internal_word[ch_map_byte_select_delayed];
220244

221245
delay #(
222246
.DATA_WIDTH (8),
223247
.DELAY_BY (1)
224248
) col_map_data_delay (
225-
.clk_i (clk100m_i),
249+
.clk_i (vga_clk_i),
226250
.arstn_i (arstn_i),
227251
.data_i (col_map_data_internal),
228252
.data_o (col_map_data_internal_delayed)
@@ -240,7 +264,7 @@ module vgachargen
240264
.ADDR_WIDTH (10)
241265
) col_map (
242266
.clka_i (clk_i),
243-
.clkb_i (clk100m_i),
267+
.clkb_i (vga_clk_i),
244268
.addra_i (col_map_addr_i),
245269
.addrb_i (ch_map_addr_internal[$left(ch_map_addr_internal):2]),
246270
.wea_i (col_map_be_gated),
@@ -277,7 +301,7 @@ module vgachargen
277301
assign vga_vs_next = vga_vs_delayed;
278302
assign vga_hs_next = vga_hs_delayed;
279303

280-
always_ff @(posedge clk100m_i or negedge arstn_i) begin
304+
always_ff @(posedge vga_clk_i or negedge arstn_i) begin
281305
if (!arstn_i) begin
282306
vga_r_ff <= '0;
283307
vga_g_ff <= '0;
@@ -309,7 +333,8 @@ module clk_divider # (
309333
input logic arstn_i,
310334
output logic strb_o
311335
);
312-
localparam int unsigned COUNTER_WIDTH = (DIVISOR > 1) ? $clog2(DIVISOR) : 1;
336+
337+
localparam int unsigned COUNTER_WIDTH = $clog2(DIVISOR);
313338

314339
logic [COUNTER_WIDTH-1:0] counter_next;
315340
logic [COUNTER_WIDTH-1:0] counter_ff;
@@ -394,28 +419,6 @@ module index_generator
394419

395420
endmodule
396421

397-
module single_port_ro_bram #(
398-
parameter INIT_FILE_NAME = "",
399-
parameter INIT_FILE_IS_BIN = 0,
400-
parameter int unsigned DATA_WIDTH = 2,
401-
parameter int unsigned ADDR_WIDTH = 4,
402-
localparam int unsigned DEPTH_WORDS = 2 ** ADDR_WIDTH
403-
) (
404-
input logic clk_i,
405-
input logic [ADDR_WIDTH-1:0] addr_i,
406-
output logic [DATA_WIDTH-1:0] dout_o
407-
);
408-
logic [DATA_WIDTH-1:0] mem[DEPTH_WORDS];
409-
410-
if (INIT_FILE_IS_BIN) initial $readmemb(INIT_FILE_NAME, mem, 0, DEPTH_WORDS-1);
411-
else initial $readmemh(INIT_FILE_NAME, mem, 0, DEPTH_WORDS-1);
412-
413-
always_ff @(posedge clk_i) begin
414-
dout_o <= mem[addr_i];
415-
end
416-
417-
endmodule
418-
419422
module timing_generator
420423
import vgachargen_pkg::*;
421424
(
@@ -434,7 +437,6 @@ module timing_generator
434437
);
435438

436439
logic [VGA_MAX_H_WIDTH-1:0] hcount_ff;
437-
logic hcount_en;
438440
logic [VGA_MAX_H_WIDTH-1:0] hcount_next;
439441

440442
logic [VGA_MAX_V_WIDTH-1:0] vcount_ff;
@@ -602,13 +604,17 @@ module vga_block
602604
);
603605
logic clk_divider_strb;
604606

607+
if (CLK_FACTOR_25M > 1) begin
605608
clk_divider # (
606609
.DIVISOR (CLK_FACTOR_25M)
607610
) clk_divider (
608611
.clk_i,
609612
.arstn_i,
610613
.strb_o (clk_divider_strb)
611614
);
615+
end else begin
616+
assign clk_divider_strb = 1'b1;
617+
end
612618

613619
timing_generator timing_generator (
614620
.clk_i,

0 commit comments

Comments
 (0)