# HG changeset patch # User Paul Boddie # Date 1466533117 -7200 # Node ID 4658aa28f367a706630b05211078ddc5b67fd8cb # Parent 13c8893af8c79a467db6ce3927b4c0bfdf55caca Moved address preparation onto negative edges and data acquisition onto positive edges, using the have_pixels variable to indicate if a read operation needs completing at the start of a new 2MHz period. Fixed various comments and docstrings. diff -r 13c8893af8c7 -r 4658aa28f367 ULA.txt --- a/ULA.txt Tue Jun 21 16:06:47 2016 +0200 +++ b/ULA.txt Tue Jun 21 20:18:37 2016 +0200 @@ -54,20 +54,28 @@ /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\ ... ~RAS: /---\___________/---\___________ ... ~CAS: /-----\___/-\___/-----\___/-\___ ... - A B C A B C ... - F S F S ... - a b c a b c ... - s f s f ... +Address events: A B C A B C ... + Data events: F S F S ... - ~WE: ......W ... + ~RAS ops: 1 0 1 0 ... + ~CAS ops: 1 0 1 0 1 0 1 0 ... + + Address ops: a b c a b c ... + Data ops: s f s f ... + + ~WE: ......W ... PHI OUT: \_______________/--------------- ... CPU (RAM): L D ... - RnW: R ... + RnW: R ... PHI OUT: \_______/-------\_______/------- ... CPU (ROM): L D L D ... RnW: R R ... +~RAS must be high for 100ns, ~CAS must be high for 50ns. +~RAS must be low for 150ns, ~CAS must be low for 90ns. +Data is available 150ns after ~RAS goes low, 90ns after ~CAS goes low. + Here, "A" and "B" respectively indicate the row and first column addresses being latched into the RAM (on a negative edge for ~RAS and ~CAS respectively), and "C" indicates the second column address being latched into diff -r 13c8893af8c7 -r 4658aa28f367 ula.py --- a/ula.py Tue Jun 21 16:06:47 2016 +0200 +++ b/ula.py Tue Jun 21 20:18:37 2016 +0200 @@ -375,33 +375,32 @@ def posedge_ram(self): - "RAM signalling." + """ + RAM signalling. + + States handled: * _ * * _ * * _ + """ # Clock management. - # Reset addresses. + # Read 4 bits (for RAM access only). if self.cycle == 1: + + # Reset addresses. + self.ram.column_deselect() self.ram.row_deselect() - # Read the CPU address, if appropriate. - - if not self.access_ram(): - self.cpu_update_clock() - - # Set row address (for ULA access only). - - elif self.cycle == 2: + # Either read from a required address or transfer CPU data. - # Either assert a required address or propagate the CPU address. + if self.have_pixels: + self.data = (self.data & 0xf0) | self.ram.data + else: + self.cpu_update_clock() + self.cpu_transfer_low() - if self.access_ram(): - self.init_row_address(self.pixel_address) - else: - self.init_row_address(self.cpu_address) - - # Latch row address, set column address (for ULA access only). + # Latch row address. elif self.cycle == 4: @@ -409,13 +408,6 @@ self.ram.row_select(self.ram_address) - # Either assert a required address or propagate the CPU address. - - if self.access_ram(): - self.init_column_address(self.pixel_address, 0) - else: - self.init_column_address(self.cpu_address, 0) - # Latch column address. elif self.cycle == 8: @@ -431,19 +423,20 @@ else: self.cpu_transfer_select() - # Cycle handled in negedge. - - # Set column address (for ULA access only). + # Read 4 bits (for RAM access only). elif self.cycle == 32: + + # Prepare to latch column address. + self.ram.column_deselect() - # Either assert a required address or propagate the CPU address. + # Either read from a required address or transfer CPU data. if self.access_ram(): - self.init_column_address(self.pixel_address, 1) + self.data = self.ram.data << 4 else: - self.init_column_address(self.cpu_address, 1) + self.cpu_transfer_high() # Latch column address. @@ -453,15 +446,6 @@ self.ram.column_select(self.ram_address) - # Read 4 bits (for ULA access only). - - elif self.cycle == 128: - - # Advance to the next column even if an NMI is asserted. - - if self.would_access_ram(): - self.next_horizontal() - def posedge_pixel(self): "Pixel production." @@ -487,7 +471,7 @@ """ Update the state of the device. - Cycles handled: * _ _ _ * _ _ * + States handled: * * * _ _ * _ * """ # Clock management. @@ -500,28 +484,52 @@ self.pcycle = 1 self.have_pixels = 0 - # Read 4 bits (for ULA access only). + # Set row address (for RAM access only). - elif self.cycle == 16: + elif self.cycle == 2: - # Either read from a required address or transfer CPU data. + # Either assert a required address or propagate the CPU address. if self.access_ram(): - self.data = self.ram.data << 4 + self.init_row_address(self.pixel_address) + else: + self.init_row_address(self.cpu_address) + + # Latch row address, set column address (for RAM access only). + + elif self.cycle == 4: + + # Either assert a required address or propagate the CPU address. + + if self.access_ram(): + self.init_column_address(self.pixel_address, 0) else: - self.cpu_transfer_high() + self.init_column_address(self.cpu_address, 0) + + # Set column address (for RAM access only). + + elif self.cycle == 32: - # Read 4 bits (for ULA access only). + # Either assert a required address or propagate the CPU address. + + if self.access_ram(): + self.init_column_address(self.pixel_address, 1) + else: + self.init_column_address(self.cpu_address, 1) + + # Update addresses. elif self.cycle == 128: - # Either read from a required address or transfer CPU data. + # Advance to the next column even if an NMI is asserted. + + if self.would_access_ram(): + self.next_horizontal() + + # If the ULA accessed RAM, indicate that a read needs completing. if self.access_ram(): - self.data = self.data | self.ram.data self.have_pixels = 1 - else: - self.cpu_transfer_low() # Start a new cycle.